From 4c29d4c74b9f72ac9b90ad36f56225356e6fa099 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 14 Jul 2024 10:23:35 -0400 Subject: [PATCH 01/28] Vendor Gems. # Conflicts: # Library/Homebrew/Gemfile.lock --- Library/Homebrew/Gemfile | 2 + Library/Homebrew/Gemfile.lock | 2 + .../sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi | 11645 ++++++++++++++++ .../Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi | 103 + .../Homebrew/vendor/bundle/bundler/setup.rb | 1 + .../gems/concurrent-ruby-1.3.4/LICENSE.txt | 21 + .../lib/concurrent-ruby/concurrent-ruby.rb | 5 + .../lib/concurrent-ruby/concurrent.rb | 134 + .../lib/concurrent-ruby/concurrent/agent.rb | 588 + .../lib/concurrent-ruby/concurrent/array.rb | 56 + .../lib/concurrent-ruby/concurrent/async.rb | 449 + .../lib/concurrent-ruby/concurrent/atom.rb | 222 + .../concurrent/atomic/atomic_boolean.rb | 127 + .../concurrent/atomic/atomic_fixnum.rb | 144 + .../atomic/atomic_markable_reference.rb | 167 + .../concurrent/atomic/atomic_reference.rb | 135 + .../concurrent/atomic/count_down_latch.rb | 100 + .../concurrent/atomic/cyclic_barrier.rb | 128 + .../concurrent/atomic/event.rb | 109 + .../concurrent/atomic/fiber_local_var.rb | 109 + .../atomic/java_count_down_latch.rb | 43 + .../concurrent/atomic/locals.rb | 189 + .../concurrent/atomic/lock_local_var.rb | 28 + .../concurrent/atomic/mutex_atomic_boolean.rb | 68 + .../concurrent/atomic/mutex_atomic_fixnum.rb | 81 + .../atomic/mutex_count_down_latch.rb | 44 + .../concurrent/atomic/mutex_semaphore.rb | 131 + .../concurrent/atomic/read_write_lock.rb | 255 + .../atomic/reentrant_read_write_lock.rb | 379 + .../concurrent/atomic/semaphore.rb | 163 + .../concurrent/atomic/thread_local_var.rb | 111 + .../atomic_reference/atomic_direct_update.rb | 37 + .../atomic_reference/mutex_atomic.rb | 67 + .../atomic_reference/numeric_cas_wrapper.rb | 28 + .../lib/concurrent-ruby/concurrent/atomics.rb | 10 + .../collection/copy_on_notify_observer_set.rb | 107 + .../collection/copy_on_write_observer_set.rb | 111 + .../java_non_concurrent_priority_queue.rb | 84 + .../concurrent/collection/lock_free_stack.rb | 160 + .../collection/map/mri_map_backend.rb | 66 + .../map/non_concurrent_map_backend.rb | 148 + .../map/synchronized_map_backend.rb | 85 + .../collection/map/truffleruby_map_backend.rb | 14 + .../non_concurrent_priority_queue.rb | 143 + .../ruby_non_concurrent_priority_queue.rb | 160 + .../concurrent/concern/deprecation.rb | 34 + .../concurrent/concern/dereferenceable.rb | 73 + .../concurrent/concern/logging.rb | 116 + .../concurrent/concern/obligation.rb | 220 + .../concurrent/concern/observable.rb | 110 + .../concurrent/concurrent_ruby.jar | Bin 0 -> 136759 bytes .../concurrent/configuration.rb | 105 + .../concurrent-ruby/concurrent/constants.rb | 8 + .../concurrent-ruby/concurrent/dataflow.rb | 81 + .../lib/concurrent-ruby/concurrent/delay.rb | 199 + .../lib/concurrent-ruby/concurrent/errors.rb | 74 + .../concurrent-ruby/concurrent/exchanger.rb | 353 + .../executor/abstract_executor_service.rb | 131 + .../concurrent/executor/cached_thread_pool.rb | 62 + .../concurrent/executor/executor_service.rb | 185 + .../concurrent/executor/fixed_thread_pool.rb | 224 + .../concurrent/executor/immediate_executor.rb | 66 + .../executor/indirect_immediate_executor.rb | 44 + .../executor/java_executor_service.rb | 100 + .../executor/java_single_thread_executor.rb | 30 + .../executor/java_thread_pool_executor.rb | 145 + .../executor/ruby_executor_service.rb | 82 + .../executor/ruby_single_thread_executor.rb | 21 + .../executor/ruby_thread_pool_executor.rb | 373 + .../concurrent/executor/safe_task_executor.rb | 35 + .../executor/serial_executor_service.rb | 34 + .../executor/serialized_execution.rb | 107 + .../serialized_execution_delegator.rb | 28 + .../executor/simple_executor_service.rb | 103 + .../executor/single_thread_executor.rb | 57 + .../executor/thread_pool_executor.rb | 88 + .../concurrent/executor/timer_set.rb | 176 + .../concurrent-ruby/concurrent/executors.rb | 20 + .../lib/concurrent-ruby/concurrent/future.rb | 141 + .../lib/concurrent-ruby/concurrent/hash.rb | 52 + .../concurrent/immutable_struct.rb | 101 + .../lib/concurrent-ruby/concurrent/ivar.rb | 208 + .../lib/concurrent-ruby/concurrent/map.rb | 350 + .../lib/concurrent-ruby/concurrent/maybe.rb | 229 + .../concurrent/mutable_struct.rb | 239 + .../lib/concurrent-ruby/concurrent/mvar.rb | 242 + .../lib/concurrent-ruby/concurrent/options.rb | 42 + .../lib/concurrent-ruby/concurrent/promise.rb | 580 + .../concurrent-ruby/concurrent/promises.rb | 2178 +++ .../concurrent-ruby/concurrent/re_include.rb | 60 + .../concurrent/scheduled_task.rb | 331 + .../lib/concurrent-ruby/concurrent/set.rb | 64 + .../concurrent/settable_struct.rb | 139 + .../concurrent/synchronization.rb | 13 + .../abstract_lockable_object.rb | 102 + .../synchronization/abstract_object.rb | 22 + .../synchronization/abstract_struct.rb | 171 + .../concurrent/synchronization/condition.rb | 62 + .../synchronization/full_memory_barrier.rb | 29 + .../synchronization/jruby_lockable_object.rb | 15 + .../concurrent/synchronization/lock.rb | 38 + .../synchronization/lockable_object.rb | 75 + .../synchronization/mutex_lockable_object.rb | 89 + .../concurrent/synchronization/object.rb | 151 + .../synchronization/safe_initialization.rb | 36 + .../concurrent/synchronization/volatile.rb | 101 + .../thread_safe/synchronized_delegator.rb | 47 + .../concurrent/thread_safe/util.rb | 16 + .../concurrent/thread_safe/util/adder.rb | 74 + .../thread_safe/util/data_structures.rb | 52 + .../thread_safe/util/power_of_two_tuple.rb | 38 + .../concurrent/thread_safe/util/striped64.rb | 246 + .../concurrent/thread_safe/util/volatile.rb | 75 + .../thread_safe/util/xor_shift_random.rb | 50 + .../concurrent-ruby/concurrent/timer_task.rb | 361 + .../lib/concurrent-ruby/concurrent/tuple.rb | 82 + .../lib/concurrent-ruby/concurrent/tvar.rb | 222 + .../concurrent/utility/engine.rb | 45 + .../concurrent/utility/monotonic_time.rb | 19 + .../utility/native_extension_loader.rb | 77 + .../concurrent/utility/native_integer.rb | 54 + .../concurrent/utility/processor_counter.rb | 220 + .../lib/concurrent-ruby/concurrent/version.rb | 3 + .../3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt | 20 + .../gems/whirly-0.3.0/data/cli-spinners.json | 1415 ++ .../data/whirly-static-spinners.json | 274 + .../3.3.0/gems/whirly-0.3.0/lib/whirly.rb | 263 + .../gems/whirly-0.3.0/lib/whirly/spinners.rb | 7 + .../whirly-0.3.0/lib/whirly/spinners/cli.rb | 7 + .../lib/whirly/spinners/whirly.rb | 15 + .../gems/whirly-0.3.0/lib/whirly/version.rb | 5 + 131 files changed, 29990 insertions(+) create mode 100644 Library/Homebrew/sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi create mode 100644 Library/Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/LICENSE.txt create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent-ruby.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/agent.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/array.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/async.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atom.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/event.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/locals.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/semaphore.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomics.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/deprecation.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/logging.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/obligation.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/observable.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concurrent_ruby.jar create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/configuration.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/constants.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/dataflow.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/delay.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/errors.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/exchanger.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/executor_service.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/timer_set.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executors.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/future.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/hash.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/immutable_struct.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/ivar.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/map.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/maybe.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mutable_struct.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mvar.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/options.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promise.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promises.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/re_include.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/scheduled_task.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/set.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/settable_struct.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/condition.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lock.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/object.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/volatile.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/timer_task.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tuple.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tvar.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/engine.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_integer.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/processor_counter.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/version.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/cli-spinners.json create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/whirly-static-spinners.json create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/cli.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/whirly.rb create mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/version.rb diff --git a/Library/Homebrew/Gemfile b/Library/Homebrew/Gemfile index 03ca1d6111508..4eca964e9ff6a 100644 --- a/Library/Homebrew/Gemfile +++ b/Library/Homebrew/Gemfile @@ -78,8 +78,10 @@ end # vendored gems (no group) gem "addressable" +gem "concurrent-ruby" gem "patchelf" gem "plist" gem "ruby-macho" gem "sorbet-runtime" gem "warning" +gem 'whirly' diff --git a/Library/Homebrew/Gemfile.lock b/Library/Homebrew/Gemfile.lock index 18b131f10ffdc..2154f3af2a585 100644 --- a/Library/Homebrew/Gemfile.lock +++ b/Library/Homebrew/Gemfile.lock @@ -9,6 +9,7 @@ GEM coderay (1.1.3) commander (5.0.0) highline (~> 3.0.0) + concurrent-ruby (1.3.4) diff-lcs (1.5.1) docile (1.4.1) elftools (1.3.1) @@ -161,6 +162,7 @@ PLATFORMS DEPENDENCIES addressable + concurrent-ruby json_schemer kramdown method_source diff --git a/Library/Homebrew/sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi b/Library/Homebrew/sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi new file mode 100644 index 0000000000000..7116a2c6d19e0 --- /dev/null +++ b/Library/Homebrew/sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi @@ -0,0 +1,11645 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for types exported from the `concurrent-ruby` gem. +# Please instead update this file by running `bin/tapioca gem concurrent-ruby`. + + +# {include:file:README.md} +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/version.rb#1 +module Concurrent + extend ::Concurrent::Utility::EngineDetector + extend ::Concurrent::Utility::NativeExtensionLoader + extend ::Logger::Severity + extend ::Concurrent::Concern::Logging + extend ::Concurrent::Concern::Deprecation + + private + + # Abort a currently running transaction - see `Concurrent::atomically`. + # + # @raise [Transaction::AbortError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#139 + def abort_transaction; end + + # Run a block that reads and writes `TVar`s as a single atomic transaction. + # With respect to the value of `TVar` objects, the transaction is atomic, in + # that it either happens or it does not, consistent, in that the `TVar` + # objects involved will never enter an illegal state, and isolated, in that + # transactions never interfere with each other. You may recognise these + # properties from database transactions. + # + # There are some very important and unusual semantics that you must be aware of: + # + # * Most importantly, the block that you pass to atomically may be executed + # more than once. In most cases your code should be free of + # side-effects, except for via TVar. + # + # * If an exception escapes an atomically block it will abort the transaction. + # + # * It is undefined behaviour to use callcc or Fiber with atomically. + # + # * If you create a new thread within an atomically, it will not be part of + # the transaction. Creating a thread counts as a side-effect. + # + # Transactions within transactions are flattened to a single transaction. + # + # @example + # a = new TVar(100_000) + # b = new TVar(100) + # + # Concurrent::atomically do + # a.value -= 10 + # b.value += 10 + # end + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#82 + def atomically; end + + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#56 + def call_dataflow(method, executor, *inputs, &block); end + + # Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available. + # {include:file:docs-source/dataflow.md} + # + # @param inputs [Future] zero or more `Future` operations that this dataflow depends upon + # @raise [ArgumentError] if no block is given + # @raise [ArgumentError] if any of the inputs are not `IVar`s + # @return [Object] the result of all the operations + # @yield The operation to perform once all the dependencies are met + # @yieldparam inputs [Future] each of the `Future` inputs to the dataflow + # @yieldreturn [Object] the result of the block operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#34 + def dataflow(*inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#44 + def dataflow!(*inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#39 + def dataflow_with(executor, *inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#49 + def dataflow_with!(executor, *inputs, &block); end + + # Leave a transaction without committing or aborting - see `Concurrent::atomically`. + # + # @raise [Transaction::LeaveError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#144 + def leave_transaction; end + + # Returns the current time as tracked by the application monotonic clock. + # + # @param unit [Symbol] the time unit to be returned, can be either + # :float_second, :float_millisecond, :float_microsecond, :second, + # :millisecond, :microsecond, or :nanosecond default to :float_second. + # @return [Float] The current monotonic time since some unspecified + # starting point + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/monotonic_time.rb#15 + def monotonic_time(unit = T.unsafe(nil)); end + + class << self + # Abort a currently running transaction - see `Concurrent::atomically`. + # + # @raise [Transaction::AbortError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#139 + def abort_transaction; end + + # Run a block that reads and writes `TVar`s as a single atomic transaction. + # With respect to the value of `TVar` objects, the transaction is atomic, in + # that it either happens or it does not, consistent, in that the `TVar` + # objects involved will never enter an illegal state, and isolated, in that + # transactions never interfere with each other. You may recognise these + # properties from database transactions. + # + # There are some very important and unusual semantics that you must be aware of: + # + # * Most importantly, the block that you pass to atomically may be executed + # more than once. In most cases your code should be free of + # side-effects, except for via TVar. + # + # * If an exception escapes an atomically block it will abort the transaction. + # + # * It is undefined behaviour to use callcc or Fiber with atomically. + # + # * If you create a new thread within an atomically, it will not be part of + # the transaction. Creating a thread counts as a side-effect. + # + # Transactions within transactions are flattened to a single transaction. + # + # @example + # a = new TVar(100_000) + # b = new TVar(100) + # + # Concurrent::atomically do + # a.value -= 10 + # b.value += 10 + # end + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#82 + def atomically; end + + # Number of processors cores available for process scheduling. + # This method takes in account the CPU quota if the process is inside a cgroup with a + # dedicated CPU quota (typically Docker). + # Otherwise it returns the same value as #processor_count but as a Float. + # + # For performance reasons the calculated value will be memoized on the first + # call. + # + # @return [Float] number of available processors + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#194 + def available_processor_count; end + + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#56 + def call_dataflow(method, executor, *inputs, &block); end + + # The maximum number of processors cores available for process scheduling. + # Returns `nil` if there is no enforced limit, or a `Float` if the + # process is inside a cgroup with a dedicated CPU quota (typically Docker). + # + # Note that nothing prevents setting a CPU quota higher than the actual number of + # cores on the system. + # + # For performance reasons the calculated value will be memoized on the first + # call. + # + # @return [nil, Float] Maximum number of available processors as set by a cgroup CPU quota, or nil if none set + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#209 + def cpu_quota; end + + # The CPU shares requested by the process. For performance reasons the calculated + # value will be memoized on the first call. + # + # @return [Float, nil] CPU shares requested by the process, or nil if not set + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#217 + def cpu_shares; end + + # @return [Logger] Logger with provided level and output. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#37 + def create_simple_logger(level = T.unsafe(nil), output = T.unsafe(nil)); end + + # @deprecated + # @return [Logger] Logger with provided level and output. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#69 + def create_stdlib_logger(level = T.unsafe(nil), output = T.unsafe(nil)); end + + # Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available. + # {include:file:docs-source/dataflow.md} + # + # @param inputs [Future] zero or more `Future` operations that this dataflow depends upon + # @raise [ArgumentError] if no block is given + # @raise [ArgumentError] if any of the inputs are not `IVar`s + # @return [Object] the result of all the operations + # @yield The operation to perform once all the dependencies are met + # @yieldparam inputs [Future] each of the `Future` inputs to the dataflow + # @yieldreturn [Object] the result of the block operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#34 + def dataflow(*inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#44 + def dataflow!(*inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#39 + def dataflow_with(executor, *inputs, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#49 + def dataflow_with!(executor, *inputs, &block); end + + # Disables AtExit handlers including pool auto-termination handlers. + # When disabled it will be the application programmer's responsibility + # to ensure that the handlers are shutdown properly prior to application + # exit by calling `AtExit.run` method. + # + # @deprecated Has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841. + # @note this option should be needed only because of `at_exit` ordering + # issues which may arise when running some of the testing frameworks. + # E.g. Minitest's test-suite runs itself in `at_exit` callback which + # executes after the pools are already terminated. Then auto termination + # needs to be disabled and called manually after test-suite ends. + # @note This method should *never* be called + # from within a gem. It should *only* be used from within the main + # application and even then it should be used only when necessary. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#48 + def disable_at_exit_handlers!; end + + # General access point to global executors. + # + # @param executor_identifier [Symbol, Executor] symbols: + # - :fast - {Concurrent.global_fast_executor} + # - :io - {Concurrent.global_io_executor} + # - :immediate - {Concurrent.global_immediate_executor} + # @return [Executor] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#83 + def executor(executor_identifier); end + + # Global thread pool optimized for short, fast *operations*. + # + # @return [ThreadPoolExecutor] the thread pool + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#55 + def global_fast_executor; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#66 + def global_immediate_executor; end + + # Global thread pool optimized for long, blocking (IO) *tasks*. + # + # @return [ThreadPoolExecutor] the thread pool + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#62 + def global_io_executor; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#109 + def global_logger; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#113 + def global_logger=(value); end + + # Global thread pool user for global *timers*. + # + # @return [Concurrent::TimerSet] the thread pool + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#73 + def global_timer_set; end + + # Leave a transaction without committing or aborting - see `Concurrent::atomically`. + # + # @raise [Transaction::LeaveError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#144 + def leave_transaction; end + + # Returns the current time as tracked by the application monotonic clock. + # + # @param unit [Symbol] the time unit to be returned, can be either + # :float_second, :float_millisecond, :float_microsecond, :second, + # :millisecond, :microsecond, or :nanosecond default to :float_second. + # @return [Float] The current monotonic time since some unspecified + # starting point + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/monotonic_time.rb#15 + def monotonic_time(unit = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb#7 + def mutex_owned_per_thread?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#87 + def new_fast_executor(opts = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#98 + def new_io_executor(opts = T.unsafe(nil)); end + + # Number of physical processor cores on the current system. For performance + # reasons the calculated value will be memoized on the first call. + # + # On Windows the Win32 API will be queried for the `NumberOfCores from + # Win32_Processor`. This will return the total number "of cores for the + # current instance of the processor." On Unix-like operating systems either + # the `hwprefs` or `sysctl` utility will be called in a subshell and the + # returned value will be used. In the rare case where none of these methods + # work or an exception is raised the function will simply return 1. + # + # @return [Integer] number physical processor cores on the current system + # @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb + # @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx + # @see http://www.unix.com/man-page/osx/1/HWPREFS/ + # @see http://linux.die.net/man/8/sysctl + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#181 + def physical_processor_count; end + + # Number of processors seen by the OS and used for process scheduling. For + # performance reasons the calculated value will be memoized on the first + # call. + # + # When running under JRuby the Java runtime call + # `java.lang.Runtime.getRuntime.availableProcessors` will be used. According + # to the Java documentation this "value may change during a particular + # invocation of the virtual machine... [applications] should therefore + # occasionally poll this property." We still memoize this value once under + # JRuby. + # + # Otherwise Ruby's Etc.nprocessors will be used. + # + # @return [Integer] number of processors seen by the OS or Java runtime + # @see http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#availableProcessors() + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#160 + def processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#142 + def processor_counter; end + + # Use logger created by #create_simple_logger to log concurrent-ruby messages. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#63 + def use_simple_logger(level = T.unsafe(nil), output = T.unsafe(nil)); end + + # Use logger created by #create_stdlib_logger to log concurrent-ruby messages. + # + # @deprecated + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#96 + def use_stdlib_logger(level = T.unsafe(nil), output = T.unsafe(nil)); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#38 +class Concurrent::AbstractExchanger < ::Concurrent::Synchronization::Object + # @return [AbstractExchanger] a new instance of AbstractExchanger + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#44 + def initialize; end + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # + # In some edge cases when a `timeout` is given a return value of `nil` may be + # ambiguous. Specifically, if `nil` is a valid value in the exchange it will + # be impossible to tell whether `nil` is the actual return value or if it + # signifies timeout. When `nil` is a valid value in the exchange consider + # using {#exchange!} or {#try_exchange} instead. + # + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @return [Object] the value exchanged by the other thread or `nil` on timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#69 + def exchange(value, timeout = T.unsafe(nil)); end + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # + # On timeout a {Concurrent::TimeoutError} exception will be raised. + # + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @raise [Concurrent::TimeoutError] on timeout + # @return [Object] the value exchanged by the other thread + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#80 + def exchange!(value, timeout = T.unsafe(nil)); end + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # + # The return value will be a {Concurrent::Maybe} set to `Just` on success or + # `Nothing` on timeout. + # + # @example + # + # exchanger = Concurrent::Exchanger.new + # + # result = exchanger.exchange(:foo, 0.5) + # + # if result.just? + # puts result.value #=> :bar + # else + # puts 'timeout' + # end + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @return [Concurrent::Maybe] on success a `Just` maybe will be returned with + # the item exchanged by the other thread as `#value`; on timeout a + # `Nothing` maybe will be returned with {Concurrent::TimeoutError} as `#reason` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#109 + def try_exchange(value, timeout = T.unsafe(nil)); end + + private + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @raise [NotImplementedError] + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#122 + def do_exchange(value, timeout); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#41 +Concurrent::AbstractExchanger::CANCEL = T.let(T.unsafe(nil), Object) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#10 +class Concurrent::AbstractExecutorService < ::Concurrent::Synchronization::LockableObject + include ::Logger::Severity + include ::Concurrent::Concern::Logging + include ::Concurrent::ExecutorService + include ::Concurrent::Concern::Deprecation + + # Create a new thread pool. + # + # @return [AbstractExecutorService] a new instance of AbstractExecutorService + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#23 + def initialize(opts = T.unsafe(nil), &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#72 + def auto_terminate=(value); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#67 + def auto_terminate?; end + + # Returns the value of attribute fallback_policy. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#18 + def fallback_policy; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#42 + def kill; end + + # Returns the value of attribute name. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#20 + def name; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#52 + def running?; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#37 + def shutdown; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#62 + def shutdown?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#57 + def shuttingdown?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#32 + def to_s; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#47 + def wait_for_termination(timeout = T.unsafe(nil)); end + + private + + # Returns an action which executes the `fallback_policy` once the queue + # size reaches `max_queue`. The reason for the indirection of an action + # is so that the work can be deferred outside of synchronization. + # + # @param args [Array] the arguments to the task which is being handled. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#85 + def fallback_action(*args); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#126 + def ns_auto_terminate?; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#106 + def ns_execute(*args, &task); end + + # Callback method called when the executor has been killed. + # The default behavior is to do nothing. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#122 + def ns_kill_execution; end + + # Callback method called when an orderly shutdown has completed. + # The default behavior is to signal all waiting threads. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#114 + def ns_shutdown_execution; end +end + +# The set of possible fallback policies that may be set at thread pool creation. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb#15 +Concurrent::AbstractExecutorService::FALLBACK_POLICIES = T.let(T.unsafe(nil), Array) + +# An abstract implementation of local storage, with sub-classes for +# per-thread and per-fiber locals. +# +# Each execution context (EC, thread or fiber) has a lazily initialized array +# of local variable values. Each time a new local variable is created, we +# allocate an "index" for it. +# +# For example, if the allocated index is 1, that means slot #1 in EVERY EC's +# locals array will be used for the value of that variable. +# +# The good thing about using a per-EC structure to hold values, rather than +# a global, is that no synchronization is needed when reading and writing +# those values (since the structure is only ever accessed by a single +# thread). +# +# Of course, when a local variable is GC'd, 1) we need to recover its index +# for use by other new local variables (otherwise the locals arrays could +# get bigger and bigger with time), and 2) we need to null out all the +# references held in the now-unused slots (both to avoid blocking GC of those +# objects, and also to prevent "stale" values from being passed on to a new +# local when the index is reused). +# +# Because we need to null out freed slots, we need to keep references to +# ALL the locals arrays, so we can null out the appropriate slots in all of +# them. This is why we need to use a finalizer to clean up the locals array +# when the EC goes out of scope. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#35 +class Concurrent::AbstractLocals + # @return [AbstractLocals] a new instance of AbstractLocals + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#36 + def initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#89 + def fetch(index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#71 + def free_index(index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#55 + def next_index(local); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#102 + def set(index, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#43 + def synchronize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#48 + def weak_synchronize; end + + private + + # When the local goes out of scope, clean up that slot across all locals currently assigned. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#112 + def local_finalizer(index); end + + # Returns the locals for the current scope, or nil if none exist. + # + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#128 + def locals; end + + # Returns the locals for the current scope, creating them if necessary. + # + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#133 + def locals!; end + + # When a thread/fiber goes out of scope, remove the array from @all_arrays. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#119 + def thread_fiber_finalizer(array_object_id); end +end + +# `Agent` is inspired by Clojure's [agent](http://clojure.org/agents) +# function. An agent is a shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. `Agent` is (mostly) +# functionally equivalent to Clojure's agent, except where the runtime +# prevents parity. +# +# Agents are reactive, not autonomous - there is no imperative message loop +# and no blocking receive. The state of an Agent should be itself immutable +# and the `#value` of an Agent is always immediately available for reading by +# any thread without any messages, i.e. observation does not require +# cooperation or coordination. +# +# Agent action dispatches are made using the various `#send` methods. These +# methods always return immediately. At some point later, in another thread, +# the following will happen: +# +# 1. The given `action` will be applied to the state of the Agent and the +# `args`, if any were supplied. +# 2. The return value of `action` will be passed to the validator lambda, +# if one has been set on the Agent. +# 3. If the validator succeeds or if no validator was given, the return value +# of the given `action` will become the new `#value` of the Agent. See +# `#initialize` for details. +# 4. If any observers were added to the Agent, they will be notified. See +# `#add_observer` for details. +# 5. If during the `action` execution any other dispatches are made (directly +# or indirectly), they will be held until after the `#value` of the Agent +# has been changed. +# +# If any exceptions are thrown by an action function, no nested dispatches +# will occur, and the exception will be cached in the Agent itself. When an +# Agent has errors cached, any subsequent interactions will immediately throw +# an exception, until the agent's errors are cleared. Agent errors can be +# examined with `#error` and the agent restarted with `#restart`. +# +# The actions of all Agents get interleaved amongst threads in a thread pool. +# At any point in time, at most one action for each Agent is being executed. +# Actions dispatched to an agent from another single agent or thread will +# occur in the order they were sent, potentially interleaved with actions +# dispatched to the same agent from other sources. The `#send` method should +# be used for actions that are CPU limited, while the `#send_off` method is +# appropriate for actions that may block on IO. +# +# Unlike in Clojure, `Agent` cannot participate in `Concurrent::TVar` transactions. +# +# ## Example +# +# ``` +# def next_fibonacci(set = nil) +# return [0, 1] if set.nil? +# set + [set[-2..-1].reduce{|sum,x| sum + x }] +# end +# +# # create an agent with an initial value +# agent = Concurrent::Agent.new(next_fibonacci) +# +# # send a few update requests +# 5.times do +# agent.send{|set| next_fibonacci(set) } +# end +# +# # wait for them to complete +# agent.await +# +# # get the current value +# agent.value #=> [0, 1, 1, 2, 3, 5, 8] +# ``` +# +# ## Observation +# +# Agents support observers through the {Concurrent::Observable} mixin module. +# Notification of observers occurs every time an action dispatch returns and +# the new value is successfully validated. Observation will *not* occur if the +# action raises an exception, if validation fails, or when a {#restart} occurs. +# +# When notified the observer will receive three arguments: `time`, `old_value`, +# and `new_value`. The `time` argument is the time at which the value change +# occurred. The `old_value` is the value of the Agent when the action began +# processing. The `new_value` is the value to which the Agent was set when the +# action completed. Note that `old_value` and `new_value` may be the same. +# This is not an error. It simply means that the action returned the same +# value. +# +# ## Nested Actions +# +# It is possible for an Agent action to post further actions back to itself. +# The nested actions will be enqueued normally then processed *after* the +# outer action completes, in the order they were sent, possibly interleaved +# with action dispatches from other threads. Nested actions never deadlock +# with one another and a failure in a nested action will never affect the +# outer action. +# +# Nested actions can be called using the Agent reference from the enclosing +# scope or by passing the reference in as a "send" argument. Nested actions +# cannot be post using `self` from within the action block/proc/lambda; `self` +# in this context will not reference the Agent. The preferred method for +# dispatching nested actions is to pass the Agent as an argument. This allows +# Ruby to more effectively manage the closing scope. +# +# Prefer this: +# +# ``` +# agent = Concurrent::Agent.new(0) +# agent.send(agent) do |value, this| +# this.send {|v| v + 42 } +# 3.14 +# end +# agent.value #=> 45.14 +# ``` +# +# Over this: +# +# ``` +# agent = Concurrent::Agent.new(0) +# agent.send do |value| +# agent.send {|v| v + 42 } +# 3.14 +# end +# ``` +# +# +# **NOTE** Never, *under any circumstances*, call any of the "await" methods +# ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action +# block/proc/lambda. The call will block the Agent and will always fail. +# Calling either {#await} or {#wait} (with a timeout of `nil`) will +# hopelessly deadlock the Agent with no possibility of recovery. +# +# @see http://clojure.org/Agents Clojure Agents +# @see http://clojure.org/state Values and Change - Clojure's approach to Identity and State +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#145 +class Concurrent::Agent < ::Concurrent::Synchronization::LockableObject + include ::Concurrent::Concern::Observable + + # Create a new `Agent` with the given initial value and options. + # + # The `:validator` option must be `nil` or a side-effect free proc/lambda + # which takes one argument. On any intended value change the validator, if + # provided, will be called. If the new value is invalid the validator should + # return `false` or raise an error. + # + # The `:error_handler` option must be `nil` or a proc/lambda which takes two + # arguments. When an action raises an error or validation fails, either by + # returning false or raising an error, the error handler will be called. The + # arguments to the error handler will be a reference to the agent itself and + # the error object which was raised. + # + # The `:error_mode` may be either `:continue` (the default if an error + # handler is given) or `:fail` (the default if error handler nil or not + # given). + # + # If an action being run by the agent throws an error or doesn't pass + # validation the error handler, if present, will be called. After the + # handler executes if the error mode is `:continue` the Agent will continue + # as if neither the action that caused the error nor the error itself ever + # happened. + # + # If the mode is `:fail` the Agent will become {#failed?} and will stop + # accepting new action dispatches. Any previously queued actions will be + # held until {#restart} is called. The {#value} method will still work, + # returning the value of the Agent before the error. + # + # @option opts + # @option opts + # @option opts + # @param initial [Object] the initial value + # @param opts [Hash] the configuration options + # @return [Agent] a new instance of Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#220 + def initialize(initial, opts = T.unsafe(nil)); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Appropriate for actions that may block on IO. + # + # @param action [Proc] the action dispatch to be enqueued + # @return [Concurrent::Agent] self + # @see #send_off + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#331 + def <<(action); end + + # Blocks the current thread (indefinitely!) until all actions dispatched + # thus far, from this thread or nested by the Agent, have occurred. Will + # block when {#failed?}. Will never return if a failed Agent is {#restart} + # with `:clear_actions` true. + # + # Returns a reference to `self` to support method chaining: + # + # ``` + # current_value = agent.await.value + # ``` + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @return [Boolean] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#350 + def await; end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#363 + def await_for(timeout); end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @raise [Concurrent::TimeoutError] when timout is reached + # @return [Boolean] true if all actions complete before timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#377 + def await_for!(timeout); end + + # The current value (state) of the Agent, irrespective of any pending or + # in-progress actions. The value is always available and is non-blocking. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#229 + def deref; end + + # When {#failed?} and {#error_mode} is `:fail`, returns the error object + # which caused the failure, else `nil`. When {#error_mode} is `:continue` + # will *always* return `nil`. + # + # @return [nil, Error] the error which caused the failure when {#failed?} + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#240 + def error; end + + # The error mode this Agent is operating in. See {#initialize} for details. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#184 + def error_mode; end + + # Is the Agent in a failed state? + # + # @return [Boolean] + # @see #restart + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#402 + def failed?; end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#294 + def post(*args, &action); end + + # When {#failed?} and {#error_mode} is `:fail`, returns the error object + # which caused the failure, else `nil`. When {#error_mode} is `:continue` + # will *always* return `nil`. + # + # @return [nil, Error] the error which caused the failure when {#failed?} + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#240 + def reason; end + + # When an Agent is {#failed?}, changes the Agent {#value} to `new_value` + # then un-fails the Agent so that action dispatches are allowed again. If + # the `:clear_actions` option is give and true, any actions queued on the + # Agent that were being held while it was failed will be discarded, + # otherwise those held actions will proceed. The `new_value` must pass the + # validator if any, or `restart` will raise an exception and the Agent will + # remain failed with its old {#value} and {#error}. Observers, if any, will + # not be notified of the new state. + # + # @option opts + # @param new_value [Object] the new value for the Agent once restarted + # @param opts [Hash] the configuration options + # @raise [Concurrent:AgentError] when not failed + # @return [Boolean] true + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#424 + def restart(new_value, opts = T.unsafe(nil)); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#278 + def send(*args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @raise [Concurrent::Agent::Error] if the Agent is {#failed?} + # @return [Boolean] true if the action is successfully enqueued + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#287 + def send!(*args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#294 + def send_off(*args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @raise [Concurrent::Agent::Error] if the Agent is {#failed?} + # @return [Boolean] true if the action is successfully enqueued + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#302 + def send_off!(*args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @param executor [Concurrent::ExecutorService] the executor on which the + # action is to be dispatched + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#311 + def send_via(executor, *args, &action); end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param args [Array] zero or more arguments to be passed to + # the action + # @param action [Proc] the action dispatch to be enqueued + # @param executor [Concurrent::ExecutorService] the executor on which the + # action is to be dispatched + # @raise [Concurrent::Agent::Error] if the Agent is {#failed?} + # @return [Boolean] true if the action is successfully enqueued + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam value [Object] the current {#value} of the Agent + # @yieldparam args [Array] zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#319 + def send_via!(executor, *args, &action); end + + # Is the Agent in a failed state? + # + # @return [Boolean] + # @see #restart + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#402 + def stopped?; end + + # The current value (state) of the Agent, irrespective of any pending or + # in-progress actions. The value is always available and is non-blocking. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#229 + def value; end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. Will block indefinitely when timeout is nil or not given. + # + # Provided mainly for consistency with other classes in this library. Prefer + # the various `await` methods instead. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#393 + def wait(timeout = T.unsafe(nil)); end + + private + + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#510 + def enqueue_action_job(action, args, executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#516 + def enqueue_await_job(latch); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#543 + def execute_next_job; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#576 + def handle_error(error); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#529 + def ns_enqueue_job(job, index = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#584 + def ns_find_last_job_for_thread; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#490 + def ns_initialize(initial, opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#539 + def ns_post_next_job; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#570 + def ns_validate(value); end + + class << self + # Blocks the current thread (indefinitely!) until all actions dispatched + # thus far to all the given Agents, from this thread or nested by the + # given Agents, have occurred. Will block when any of the agents are + # failed. Will never return if a failed Agent is restart with + # `:clear_actions` true. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param agents [Array] the Agents on which to wait + # @return [Boolean] true + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#449 + def await(*agents); end + + # Blocks the current thread until all actions dispatched thus far to all + # the given Agents, from this thread or nested by the given Agents, have + # occurred, or the timeout (in seconds) has elapsed. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @param agents [Array] the Agents on which to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#463 + def await_for(timeout, *agents); end + + # Blocks the current thread until all actions dispatched thus far to all + # the given Agents, from this thread or nested by the given Agents, have + # occurred, or the timeout (in seconds) has elapsed. + # + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @param timeout [Float] the maximum number of seconds to wait + # @param agents [Array] the Agents on which to wait + # @raise [Concurrent::TimeoutError] when timout is reached + # @return [Boolean] true if all actions complete before timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#482 + def await_for!(timeout, *agents); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#154 +Concurrent::Agent::AWAIT_ACTION = T.let(T.unsafe(nil), Proc) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#151 +Concurrent::Agent::AWAIT_FLAG = T.let(T.unsafe(nil), Object) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#157 +Concurrent::Agent::DEFAULT_ERROR_HANDLER = T.let(T.unsafe(nil), Proc) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#160 +Concurrent::Agent::DEFAULT_VALIDATOR = T.let(T.unsafe(nil), Proc) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#148 +Concurrent::Agent::ERROR_MODES = T.let(T.unsafe(nil), Array) + +# Raised during action processing or any other time in an Agent's lifecycle. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#167 +class Concurrent::Agent::Error < ::StandardError + # @return [Error] a new instance of Error + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#168 + def initialize(message = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#163 +class Concurrent::Agent::Job < ::Struct + # Returns the value of attribute action + # + # @return [Object] the current value of action + def action; end + + # Sets the attribute action + # + # @param value [Object] the value to set the attribute action to. + # @return [Object] the newly set value + def action=(_); end + + # Returns the value of attribute args + # + # @return [Object] the current value of args + def args; end + + # Sets the attribute args + # + # @param value [Object] the value to set the attribute args to. + # @return [Object] the newly set value + def args=(_); end + + # Returns the value of attribute caller + # + # @return [Object] the current value of caller + def caller; end + + # Sets the attribute caller + # + # @param value [Object] the value to set the attribute caller to. + # @return [Object] the newly set value + def caller=(_); end + + # Returns the value of attribute executor + # + # @return [Object] the current value of executor + def executor; end + + # Sets the attribute executor + # + # @param value [Object] the value to set the attribute executor to. + # @return [Object] the newly set value + def executor=(_); end + + class << self + def [](*_arg0); end + def inspect; end + def keyword_init?; end + def members; end + def new(*_arg0); end + end +end + +# Raised when a new value obtained during action processing or at `#restart` +# fails validation. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#176 +class Concurrent::Agent::ValidationError < ::Concurrent::Agent::Error + # @return [ValidationError] a new instance of ValidationError + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/agent.rb#177 + def initialize(message = T.unsafe(nil)); end +end + +# A thread-safe subclass of Array. This version locks against the object +# itself for every method call, ensuring only one thread can be reading +# or writing at a time. This includes iteration methods like `#each`. +# +# @note `a += b` is **not** a **thread-safe** operation on +# `Concurrent::Array`. It reads array `a`, then it creates new `Concurrent::Array` +# which is concatenation of `a` and `b`, then it writes the concatenation to `a`. +# The read and write are independent operations they do not form a single atomic +# operation therefore when two `+=` operations are executed concurrently updates +# may be lost. Use `#concat` instead. +# @see http://ruby-doc.org/core/Array.html Ruby standard library `Array` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/array.rb#53 +class Concurrent::Array < ::Array; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/array.rb#22 +Concurrent::ArrayImplementation = Array + +# A mixin module that provides simple asynchronous behavior to a class, +# turning it into a simple actor. Loosely based on Erlang's +# [gen_server](http://www.erlang.org/doc/man/gen_server.html), but without +# supervision or linking. +# +# A more feature-rich {Concurrent::Actor} is also available when the +# capabilities of `Async` are too limited. +# +# ```cucumber +# Feature: +# As a stateful, plain old Ruby class +# I want safe, asynchronous behavior +# So my long-running methods don't block the main thread +# ``` +# +# The `Async` module is a way to mix simple yet powerful asynchronous +# capabilities into any plain old Ruby object or class, turning each object +# into a simple Actor. Method calls are processed on a background thread. The +# caller is free to perform other actions while processing occurs in the +# background. +# +# Method calls to the asynchronous object are made via two proxy methods: +# `async` (alias `cast`) and `await` (alias `call`). These proxy methods post +# the method call to the object's background thread and return a "future" +# which will eventually contain the result of the method call. +# +# This behavior is loosely patterned after Erlang's `gen_server` behavior. +# When an Erlang module implements the `gen_server` behavior it becomes +# inherently asynchronous. The `start` or `start_link` function spawns a +# process (similar to a thread but much more lightweight and efficient) and +# returns the ID of the process. Using the process ID, other processes can +# send messages to the `gen_server` via the `cast` and `call` methods. Unlike +# Erlang's `gen_server`, however, `Async` classes do not support linking or +# supervision trees. +# +# ## Basic Usage +# +# When this module is mixed into a class, objects of the class become inherently +# asynchronous. Each object gets its own background thread on which to post +# asynchronous method calls. Asynchronous method calls are executed in the +# background one at a time in the order they are received. +# +# To create an asynchronous class, simply mix in the `Concurrent::Async` module: +# +# ``` +# class Hello +# include Concurrent::Async +# +# def hello(name) +# "Hello, #{name}!" +# end +# end +# ``` +# +# Mixing this module into a class provides each object two proxy methods: +# `async` and `await`. These methods are thread safe with respect to the +# enclosing object. The former proxy allows methods to be called +# asynchronously by posting to the object's internal thread. The latter proxy +# allows a method to be called synchronously but does so safely with respect +# to any pending asynchronous method calls and ensures proper ordering. Both +# methods return a {Concurrent::IVar} which can be inspected for the result +# of the proxied method call. Calling a method with `async` will return a +# `:pending` `IVar` whereas `await` will return a `:complete` `IVar`. +# +# ``` +# class Echo +# include Concurrent::Async +# +# def echo(msg) +# print "#{msg}\n" +# end +# end +# +# horn = Echo.new +# horn.echo('zero') # synchronous, not thread-safe +# # returns the actual return value of the method +# +# horn.async.echo('one') # asynchronous, non-blocking, thread-safe +# # returns an IVar in the :pending state +# +# horn.await.echo('two') # synchronous, blocking, thread-safe +# # returns an IVar in the :complete state +# ``` +# +# ## Let It Fail +# +# The `async` and `await` proxy methods have built-in error protection based +# on Erlang's famous "let it fail" philosophy. Instance methods should not be +# programmed defensively. When an exception is raised by a delegated method +# the proxy will rescue the exception, expose it to the caller as the `reason` +# attribute of the returned future, then process the next method call. +# +# ## Calling Methods Internally +# +# External method calls should *always* use the `async` and `await` proxy +# methods. When one method calls another method, the `async` proxy should +# rarely be used and the `await` proxy should *never* be used. +# +# When an object calls one of its own methods using the `await` proxy the +# second call will be enqueued *behind* the currently running method call. +# Any attempt to wait on the result will fail as the second call will never +# run until after the current call completes. +# +# Calling a method using the `await` proxy from within a method that was +# itself called using `async` or `await` will irreversibly deadlock the +# object. Do *not* do this, ever. +# +# ## Instance Variables and Attribute Accessors +# +# Instance variables do not need to be thread-safe so long as they are private. +# Asynchronous method calls are processed in the order they are received and +# are processed one at a time. Therefore private instance variables can only +# be accessed by one thread at a time. This is inherently thread-safe. +# +# When using private instance variables within asynchronous methods, the best +# practice is to read the instance variable into a local variable at the start +# of the method then update the instance variable at the *end* of the method. +# This way, should an exception be raised during method execution the internal +# state of the object will not have been changed. +# +# ### Reader Attributes +# +# The use of `attr_reader` is discouraged. Internal state exposed externally, +# when necessary, should be done through accessor methods. The instance +# variables exposed by these methods *must* be thread-safe, or they must be +# called using the `async` and `await` proxy methods. These two approaches are +# subtly different. +# +# When internal state is accessed via the `async` and `await` proxy methods, +# the returned value represents the object's state *at the time the call is +# processed*, which may *not* be the state of the object at the time the call +# is made. +# +# To get the state *at the current* time, irrespective of an enqueued method +# calls, a reader method must be called directly. This is inherently unsafe +# unless the instance variable is itself thread-safe, preferably using one +# of the thread-safe classes within this library. Because the thread-safe +# classes within this library are internally-locking or non-locking, they can +# be safely used from within asynchronous methods without causing deadlocks. +# +# Generally speaking, the best practice is to *not* expose internal state via +# reader methods. The best practice is to simply use the method's return value. +# +# ### Writer Attributes +# +# Writer attributes should never be used with asynchronous classes. Changing +# the state externally, even when done in the thread-safe way, is not logically +# consistent. Changes to state need to be timed with respect to all asynchronous +# method calls which my be in-process or enqueued. The only safe practice is to +# pass all necessary data to each method as arguments and let the method update +# the internal state as necessary. +# +# ## Class Constants, Variables, and Methods +# +# ### Class Constants +# +# Class constants do not need to be thread-safe. Since they are read-only and +# immutable they may be safely read both externally and from within +# asynchronous methods. +# +# ### Class Variables +# +# Class variables should be avoided. Class variables represent shared state. +# Shared state is anathema to concurrency. Should there be a need to share +# state using class variables they *must* be thread-safe, preferably +# using the thread-safe classes within this library. When updating class +# variables, never assign a new value/object to the variable itself. Assignment +# is not thread-safe in Ruby. Instead, use the thread-safe update functions +# of the variable itself to change the value. +# +# The best practice is to *never* use class variables with `Async` classes. +# +# ### Class Methods +# +# Class methods which are pure functions are safe. Class methods which modify +# class variables should be avoided, for all the reasons listed above. +# +# ## An Important Note About Thread Safe Guarantees +# +# > Thread safe guarantees can only be made when asynchronous method calls +# > are not mixed with direct method calls. Use only direct method calls +# > when the object is used exclusively on a single thread. Use only +# > `async` and `await` when the object is shared between threads. Once you +# > call a method using `async` or `await`, you should no longer call methods +# > directly on the object. Use `async` and `await` exclusively from then on. +# +# @example +# +# class Echo +# include Concurrent::Async +# +# def echo(msg) +# print "#{msg}\n" +# end +# end +# +# horn = Echo.new +# horn.echo('zero') # synchronous, not thread-safe +# # returns the actual return value of the method +# +# horn.async.echo('one') # asynchronous, non-blocking, thread-safe +# # returns an IVar in the :pending state +# +# horn.await.echo('two') # synchronous, blocking, thread-safe +# # returns an IVar in the :complete state +# @see Concurrent::Actor +# @see https://en.wikipedia.org/wiki/Actor_model "Actor Model" at Wikipedia +# @see http://www.erlang.org/doc/man/gen_server.html Erlang gen_server +# @see http://c2.com/cgi/wiki?LetItCrash "Let It Crash" at http://c2.com/ +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#217 +module Concurrent::Async + mixes_in_class_methods ::Concurrent::Async::ClassMethods + + # Causes the chained method call to be performed asynchronously on the + # object's thread. The delegated method will return a future in the + # `:pending` state and the method call will have been scheduled on the + # object's thread. The final disposition of the method call can be obtained + # by inspecting the returned future. + # + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of + # the requested method + # @return [Concurrent::IVar] the pending result of the asynchronous operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#412 + def async; end + + # Causes the chained method call to be performed synchronously on the + # current thread. The delegated will return a future in either the + # `:fulfilled` or `:rejected` state and the delegated method will have + # completed. The final disposition of the delegated method can be obtained + # by inspecting the returned future. + # + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of the + # requested method + # @return [Concurrent::IVar] the completed result of the synchronous operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#430 + def await; end + + # Causes the chained method call to be performed synchronously on the + # current thread. The delegated will return a future in either the + # `:fulfilled` or `:rejected` state and the delegated method will have + # completed. The final disposition of the delegated method can be obtained + # by inspecting the returned future. + # + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of the + # requested method + # @return [Concurrent::IVar] the completed result of the synchronous operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#430 + def call; end + + # Causes the chained method call to be performed asynchronously on the + # object's thread. The delegated method will return a future in the + # `:pending` state and the method call will have been scheduled on the + # object's thread. The final disposition of the method call can be obtained + # by inspecting the returned future. + # + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of + # the requested method + # @return [Concurrent::IVar] the pending result of the asynchronous operation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#412 + def cast; end + + # Initialize the internal serializer and other stnchronization mechanisms. + # + # @note This method *must* be called immediately upon object construction. + # This is the only way thread-safe initialization can be guaranteed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#441 + def init_synchronization; end + + class << self + # @private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#262 + def included(base); end + + # Check for the presence of a method on an object and determine if a given + # set of arguments matches the required arity. + # + # @note This check is imperfect because of the way Ruby reports the arity of + # methods with a variable number of arguments. It is possible to determine + # if too few arguments are given but impossible to determine if too many + # arguments are given. This check may also fail to recognize dynamic behavior + # of the object, such as methods simulated with `method_missing`. + # @param obj [Object] the object to check against + # @param method [Symbol] the method to check the object for + # @param args [Array] zero or more arguments for the arity check + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + # @see http://www.ruby-doc.org/core-2.1.1/Method.html#method-i-arity Method#arity + # @see http://ruby-doc.org/core-2.1.0/Object.html#method-i-respond_to-3F Object#respond_to? + # @see http://www.ruby-doc.org/core-2.1.0/BasicObject.html#method-i-method_missing BasicObject#method_missing + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#250 + def validate_argc(obj, method, *args); end + end +end + +# Delegates asynchronous, thread-safe method calls to the wrapped object. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#282 +class Concurrent::Async::AsyncDelegator < ::Concurrent::Synchronization::LockableObject + # Create a new delegator object wrapping the given delegate. + # + # @param delegate [Object] the object to wrap and delegate method calls to + # @return [AsyncDelegator] a new instance of AsyncDelegator + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#288 + def initialize(delegate); end + + # Delegates method calls to the wrapped object. + # + # @param method [Symbol] the method being called + # @param args [Array] zero or more arguments to the method + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + # @return [IVar] the result of the method call + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#305 + def method_missing(method, *args, &block); end + + # Perform all enqueued tasks. + # + # This method must be called from within the executor. It must not be + # called while already running. It will loop until the queue is empty. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#330 + def perform; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#348 + def reset_if_forked; end + + private + + # Check whether the method is responsive + # + # @param method [Symbol] the method being called + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#322 + def respond_to_missing?(method, include_private = T.unsafe(nil)); end +end + +# Delegates synchronous, thread-safe method calls to the wrapped object. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#360 +class Concurrent::Async::AwaitDelegator + # Create a new delegator object wrapping the given delegate. + # + # @param delegate [AsyncDelegator] the object to wrap and delegate method calls to + # @return [AwaitDelegator] a new instance of AwaitDelegator + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#365 + def initialize(delegate); end + + # Delegates method calls to the wrapped object. + # + # @param method [Symbol] the method being called + # @param args [Array] zero or more arguments to the method + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + # @return [IVar] the result of the method call + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#378 + def method_missing(method, *args, &block); end + + private + + # Check whether the method is responsive + # + # @param method [Symbol] the method being called + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#387 + def respond_to_missing?(method, include_private = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#269 +module Concurrent::Async::ClassMethods + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/async.rb#270 + def new(*args, **_arg1, &block); end +end + +# Atoms provide a way to manage shared, synchronous, independent state. +# +# An atom is initialized with an initial value and an optional validation +# proc. At any time the value of the atom can be synchronously and safely +# changed. If a validator is given at construction then any new value +# will be checked against the validator and will be rejected if the +# validator returns false or raises an exception. +# +# There are two ways to change the value of an atom: {#compare_and_set} and +# {#swap}. The former will set the new value if and only if it validates and +# the current value matches the new value. The latter will atomically set the +# new value to the result of running the given block if and only if that +# value validates. +# +# ## Example +# +# ``` +# def next_fibonacci(set = nil) +# return [0, 1] if set.nil? +# set + [set[-2..-1].reduce{|sum,x| sum + x }] +# end +# +# # create an atom with an initial value +# atom = Concurrent::Atom.new(next_fibonacci) +# +# # send a few update requests +# 5.times do +# atom.swap{|set| next_fibonacci(set) } +# end +# +# # get the current value +# atom.value #=> [0, 1, 1, 2, 3, 5, 8] +# ``` +# +# ## Observation +# +# Atoms support observers through the {Concurrent::Observable} mixin module. +# Notification of observers occurs every time the value of the Atom changes. +# When notified the observer will receive three arguments: `time`, `old_value`, +# and `new_value`. The `time` argument is the time at which the value change +# occurred. The `old_value` is the value of the Atom when the change began +# The `new_value` is the value to which the Atom was set when the change +# completed. Note that `old_value` and `new_value` may be the same. This is +# not an error. It simply means that the change operation returned the same +# value. +# +# Unlike in Clojure, `Atom` cannot participate in {Concurrent::TVar} transactions. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# +# @see http://clojure.org/atoms Clojure Atoms +# @see http://clojure.org/state Values and Change - Clojure's approach to Identity and State +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#95 +class Concurrent::Atom < ::Concurrent::Synchronization::Object + include ::Concurrent::Concern::Observable + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new atom with the given initial value. + # + # @option opts + # @param value [Object] The initial value + # @param opts [Hash] The options used to configure the atom + # @raise [ArgumentError] if the validator is not a `Proc` (when given) + # @return [Atom] a new instance of Atom + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#121 + def initialize(value, opts = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # Atomically sets the value of atom to the new value if and only if the + # current value of the atom is identical to the old value and the new + # value successfully validates against the (optional) validator given + # at construction. + # + # @param old_value [Object] The expected current value. + # @param new_value [Object] The intended new value. + # @return [Boolean] True if the value is changed else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#181 + def compare_and_set(old_value, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def deref; end + + # Atomically sets the value of atom to the new value without regard for the + # current value so long as the new value successfully validates against the + # (optional) validator given at construction. + # + # @param new_value [Object] The intended new value. + # @return [Object] The final value of the atom after all operations and + # validations are complete. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#198 + def reset(new_value); end + + # Atomically swaps the value of atom using the given block. The current + # value will be passed to the block, as will any arguments passed as + # arguments to the function. The new value will be validated against the + # (optional) validator proc given at construction. If validation fails the + # value will not be changed. + # + # Internally, {#swap} reads the current value, applies the block to it, and + # attempts to compare-and-set it in. Since another thread may have changed + # the value in the intervening time, it may have to retry, and does so in a + # spin loop. The net effect is that the value will always be the result of + # the application of the supplied block to a current value, atomically. + # However, because the block might be called multiple times, it must be free + # of side effects. + # + # @note The given block may be called multiple times, and thus should be free + # of side effects. + # @param args [Object] Zero or more arguments passed to the block. + # @raise [ArgumentError] When no block is given. + # @return [Object] The final value of the atom after all operations and + # validations are complete. + # @yield [value, args] Calculates a new value for the atom based on the + # current value and any supplied arguments. + # @yieldparam value [Object] The current value of the atom. + # @yieldparam args [Object] All arguments passed to the function, in order. + # @yieldreturn [Object] The intended new value of the atom. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#157 + def swap(*args); end + + # The current value of the atom. + # + # @return [Object] The current value. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def value; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_value(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_value(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_value(&block); end + + # Is the new value valid? + # + # @param new_value [Object] The intended new value. + # @return [Boolean] false if the validator function returns false or raises + # an exception else true + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atom.rb#216 + def valid?(new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def value=(value); end +end + +# A boolean value that can be updated atomically. Reads and writes to an atomic +# boolean and thread-safe and guaranteed to succeed. Reads and writes may block +# briefly but no explicit locking is required. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# Performance: +# +# ``` +# Testing with ruby 2.1.2 +# Testing with Concurrent::MutexAtomicBoolean... +# 2.790000 0.000000 2.790000 ( 2.791454) +# Testing with Concurrent::CAtomicBoolean... +# 0.740000 0.000000 0.740000 ( 0.740206) +# +# Testing with jruby 1.9.3 +# Testing with Concurrent::MutexAtomicBoolean... +# 5.240000 2.520000 7.760000 ( 3.683000) +# Testing with Concurrent::JavaAtomicBoolean... +# 3.340000 0.010000 3.350000 ( 0.855000) +# ``` +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb#119 +class Concurrent::AtomicBoolean < ::Concurrent::MutexAtomicBoolean + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb#121 + def inspect; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb#121 + def to_s; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb#82 +Concurrent::AtomicBooleanImplementation = Concurrent::MutexAtomicBoolean + +# Define update methods that use direct paths +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb#9 +module Concurrent::AtomicDirectUpdate + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb#15 + def try_update; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb#24 + def try_update!; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb#10 + def update; end +end + +# A numeric value that can be updated atomically. Reads and writes to an atomic +# fixnum and thread-safe and guaranteed to succeed. Reads and writes may block +# briefly but no explicit locking is required. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# Performance: +# +# ``` +# Testing with ruby 2.1.2 +# Testing with Concurrent::MutexAtomicFixnum... +# 3.130000 0.000000 3.130000 ( 3.136505) +# Testing with Concurrent::CAtomicFixnum... +# 0.790000 0.000000 0.790000 ( 0.785550) +# +# Testing with jruby 1.9.3 +# Testing with Concurrent::MutexAtomicFixnum... +# 5.460000 2.460000 7.920000 ( 3.715000) +# Testing with Concurrent::JavaAtomicFixnum... +# 4.520000 0.030000 4.550000 ( 1.187000) +# ``` +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb#136 +class Concurrent::AtomicFixnum < ::Concurrent::MutexAtomicFixnum + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb#138 + def inspect; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb#138 + def to_s; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb#99 +Concurrent::AtomicFixnumImplementation = Concurrent::MutexAtomicFixnum + +# An atomic reference which maintains an object reference along with a mark bit +# that can be updated atomically. +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicMarkableReference.html java.util.concurrent.atomic.AtomicMarkableReference +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#10 +class Concurrent::AtomicMarkableReference < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [AtomicMarkableReference] a new instance of AtomicMarkableReference + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#15 + def initialize(value = T.unsafe(nil), mark = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # Atomically sets the value and mark to the given updated value and + # mark given both: + # - the current value == the expected value && + # - the current mark == the expected mark + # + # that the actual value was not equal to the expected value or the + # actual mark was not equal to the expected mark + # + # @param expected_val [Object] the expected value + # @param new_val [Object] the new value + # @param expected_mark [Boolean] the expected mark + # @param new_mark [Boolean] the new mark + # @return [Boolean] `true` if successful. A `false` return indicates + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#33 + def compare_and_set(expected_val, new_val, expected_mark, new_mark); end + + # Atomically sets the value and mark to the given updated value and + # mark given both: + # - the current value == the expected value && + # - the current mark == the expected mark + # + # that the actual value was not equal to the expected value or the + # actual mark was not equal to the expected mark + # + # @param expected_val [Object] the expected value + # @param new_val [Object] the new value + # @param expected_mark [Boolean] the expected mark + # @param new_mark [Boolean] the new mark + # @return [Boolean] `true` if successful. A `false` return indicates + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#33 + def compare_and_swap(expected_val, new_val, expected_mark, new_mark); end + + # Gets the current reference and marked values. + # + # @return [Array] the current reference and marked values + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#64 + def get; end + + # Gets the current marked value + # + # @return [Boolean] the current marked value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#78 + def mark; end + + # Gets the current marked value + # + # @return [Boolean] the current marked value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#78 + def marked?; end + + # _Unconditionally_ sets to the given value of both the reference and + # the mark. + # + # @param new_val [Object] the new value + # @param new_mark [Boolean] the new mark + # @return [Array] both the new value and the new mark + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#91 + def set(new_val, new_mark); end + + # Pass the current value to the given block, replacing it with the + # block's result. Simply return nil if update fails. + # + # the update failed + # + # @return [Array] the new value and marked state, or nil if + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam old_val [Object] the starting value of the atomic reference + # @yieldparam old_mark [Boolean] the starting state of marked + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#152 + def try_update; end + + # Pass the current value to the given block, replacing it + # with the block's result. Raise an exception if the update + # fails. + # + # @raise [Concurrent::ConcurrentUpdateError] if the update fails + # @return [Array] the new value and marked state + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam old_val [Object] the starting value of the atomic reference + # @yieldparam old_mark [Boolean] the starting state of marked + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#128 + def try_update!; end + + # Pass the current value and marked state to the given block, replacing it + # with the block's results. May retry if the value changes during the + # block's execution. + # + # @return [Array] the new value and new mark + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam old_val [Object] the starting value of the atomic reference + # @yieldparam old_mark [Boolean] the starting state of marked + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#105 + def update; end + + # Gets the current value of the reference + # + # @return [Object] the current value of the reference + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#71 + def value; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_reference(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb#163 + def immutable_array(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def reference; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def reference=(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_reference(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_reference(&block); end +end + +# Special "compare and set" handling of numeric values. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb#7 +module Concurrent::AtomicNumericCompareAndSetWrapper + # Atomically sets the value to the given updated value if + # the current value == the expected value. + # + # that the actual value was not equal to the expected value. + # + # @param old_value [Object] the expected value + # @param new_value [Object] the new value + # @return [Boolean] `true` if successful. A `false` return indicates + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb#10 + def compare_and_set(old_value, new_value); end +end + +# An object reference that may be updated atomically. All read and write +# operations have java volatile semantic. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb#126 +class Concurrent::AtomicReference < ::Concurrent::MutexAtomicReference + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb#129 + def inspect; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb#129 + def to_s; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb#18 +Concurrent::AtomicReferenceImplementation = Concurrent::MutexAtomicReference + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/set.rb#30 +class Concurrent::CRubySet < ::Set + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#18 + def initialize(*args, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def &(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def +(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def -(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def <(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def <<(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def <=(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def <=>(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def ==(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def ===(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def >(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def >=(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def ^(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def add(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def add?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def classify(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def clear(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def collect!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def compare_by_identity(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def compare_by_identity?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def delete(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def delete?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def delete_if(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def difference(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def disjoint?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def divide(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def each(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def empty?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def eql?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def filter!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def flatten(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def flatten!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def flatten_merge(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def freeze(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def hash(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def include?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def inspect(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def intersect?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def intersection(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def join(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def keep_if(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def length(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def map!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def member?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def merge(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def pretty_print(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def pretty_print_cycle(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def proper_subset?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def proper_superset?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def reject!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def replace(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def reset(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def select!(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def size(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def subset?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def subtract(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def superset?(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def to_a(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def to_s(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def to_set(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def union(*args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#32 + def |(*args); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#23 + def initialize_copy(other); end +end + +# A thread pool that dynamically grows and shrinks to fit the current workload. +# New threads are created as needed, existing threads are reused, and threads +# that remain idle for too long are killed and removed from the pool. These +# pools are particularly suited to applications that perform a high volume of +# short-lived tasks. +# +# On creation a `CachedThreadPool` has zero running threads. New threads are +# created on the pool as new operations are `#post`. The size of the pool +# will grow until `#max_length` threads are in the pool or until the number +# of threads exceeds the number of running and pending operations. When a new +# operation is post to the pool the first available idle thread will be tasked +# with the new operation. +# +# Should a thread crash for any reason the thread will immediately be removed +# from the pool. Similarly, threads which remain idle for an extended period +# of time will be killed and reclaimed. Thus these thread pools are very +# efficient at reclaiming unused resources. +# +# The API and behavior of this class are based on Java's `CachedThreadPool` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb#27 +class Concurrent::CachedThreadPool < ::Concurrent::ThreadPoolExecutor + # Create a new thread pool. + # + # @option opts + # @param opts [Hash] the options defining pool behavior. + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # @return [CachedThreadPool] a new instance of CachedThreadPool + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool-- + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb#39 + def initialize(opts = T.unsafe(nil)); end + + private + + # Create a new thread pool. + # + # @option opts + # @param opts [Hash] the options defining pool behavior. + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool-- + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb#51 + def ns_initialize(opts); end +end + +# Raised when an asynchronous operation is cancelled before execution. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#9 +class Concurrent::CancelledOperationError < ::Concurrent::Error; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#4 +module Concurrent::Collection; end + +# A thread safe observer set implemented using copy-on-read approach: +# observers are added and removed from a thread safe collection; every time +# a notification is required the internal data structure is copied to +# prevent concurrency issues +# +# @api private +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#12 +class Concurrent::Collection::CopyOnNotifyObserverSet < ::Concurrent::Synchronization::LockableObject + # @api private + # @return [CopyOnNotifyObserverSet] a new instance of CopyOnNotifyObserverSet + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#14 + def initialize; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#20 + def add_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#55 + def count_observers; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#39 + def delete_observer(observer); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#47 + def delete_observers; end + + # Notifies all registered observers with optional args and deletes them. + # + # @api private + # @param args [Object] arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#72 + def notify_and_delete_observers(*args, &block); end + + # Notifies all registered observers with optional args + # + # @api private + # @param args [Object] arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#62 + def notify_observers(*args, &block); end + + protected + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#80 + def ns_initialize; end + + private + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#86 + def duplicate_and_clear_observers; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#94 + def duplicate_observers; end + + # @api private + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#98 + def notify_to(observers, *args); end +end + +# A thread safe observer set implemented using copy-on-write approach: +# every time an observer is added or removed the whole internal data structure is +# duplicated and replaced with a new one. +# +# @api private +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#11 +class Concurrent::Collection::CopyOnWriteObserverSet < ::Concurrent::Synchronization::LockableObject + # @api private + # @return [CopyOnWriteObserverSet] a new instance of CopyOnWriteObserverSet + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#13 + def initialize; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#19 + def add_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#56 + def count_observers; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#40 + def delete_observer(observer); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#50 + def delete_observers; end + + # Notifies all registered observers with optional args and deletes them. + # + # @api private + # @param args [Object] arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#72 + def notify_and_delete_observers(*args, &block); end + + # Notifies all registered observers with optional args + # + # @api private + # @param args [Object] arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#63 + def notify_observers(*args, &block); end + + protected + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#80 + def ns_initialize; end + + private + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#102 + def clear_observers_and_return_old; end + + # @api private + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#86 + def notify_to(observers, *args); end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#94 + def observers; end + + # @api private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#98 + def observers=(new_set); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#10 +Concurrent::Collection::MapImplementation = Concurrent::Collection::MriMapBackend + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#10 +class Concurrent::Collection::MriMapBackend < ::Concurrent::Collection::NonConcurrentMapBackend + # @return [MriMapBackend] a new instance of MriMapBackend + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#12 + def initialize(options = T.unsafe(nil), &default_proc); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#17 + def []=(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#61 + def clear; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#33 + def compute(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#21 + def compute_if_absent(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#29 + def compute_if_present(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#53 + def delete(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#57 + def delete_pair(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#49 + def get_and_set(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#37 + def merge_pair(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#45 + def replace_if_exists(key, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#41 + def replace_pair(key, old_value, new_value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#9 +class Concurrent::Collection::NonConcurrentMapBackend + # WARNING: all public methods of the class must operate on the @backend + # directly without calling each other. This is important because of the + # SynchronizedMapBackend which uses a non-reentrant mutex for performance + # reasons. + # + # @return [NonConcurrentMapBackend] a new instance of NonConcurrentMapBackend + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#15 + def initialize(options = T.unsafe(nil), &default_proc); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#21 + def [](key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#25 + def []=(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#94 + def clear; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#59 + def compute(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#29 + def compute_if_absent(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#53 + def compute_if_present(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#81 + def delete(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#85 + def delete_pair(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#99 + def each_pair; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#71 + def get_and_set(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#110 + def get_or_default(key, default_value); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#77 + def key?(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#63 + def merge_pair(key, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#46 + def replace_if_exists(key, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#37 + def replace_pair(key, old_value, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#106 + def size; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#130 + def dupped_backend; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#124 + def initialize_copy(other); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#134 + def pair?(key, expected_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#116 + def set_backend(default_proc); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#138 + def store_computed_value(key, new_value); end +end + +# A queue collection in which the elements are sorted based on their +# comparison (spaceship) operator `<=>`. Items are added to the queue +# at a position relative to their priority. On removal the element +# with the "highest" priority is removed. By default the sort order is +# from highest to lowest, but a lowest-to-highest sort order can be +# set on construction. +# +# The API is based on the `Queue` class from the Ruby standard library. +# +# The pure Ruby implementation, `RubyNonConcurrentPriorityQueue` uses a heap algorithm +# stored in an array. The algorithm is based on the work of Robert Sedgewick +# and Kevin Wayne. +# +# The JRuby native implementation is a thin wrapper around the standard +# library `java.util.NonConcurrentPriorityQueue`. +# +# When running under JRuby the class `NonConcurrentPriorityQueue` extends `JavaNonConcurrentPriorityQueue`. +# When running under all other interpreters it extends `RubyNonConcurrentPriorityQueue`. +# +# @note This implementation is *not* thread safe. +# @see http://en.wikipedia.org/wiki/Priority_queue +# @see http://ruby-doc.org/stdlib-2.0.0/libdoc/thread/rdoc/Queue.html +# @see http://algs4.cs.princeton.edu/24pq/index.php#2.6 +# @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html +# @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb#50 +class Concurrent::Collection::NonConcurrentPriorityQueue < ::Concurrent::Collection::RubyNonConcurrentPriorityQueue + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def <<(item); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def deq; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def enq(item); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#48 + def has_priority?(item); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def shift; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#54 + def size; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb#10 +Concurrent::Collection::NonConcurrentPriorityQueueImplementation = Concurrent::Collection::RubyNonConcurrentPriorityQueue + +# A queue collection in which the elements are sorted based on their +# comparison (spaceship) operator `<=>`. Items are added to the queue +# at a position relative to their priority. On removal the element +# with the "highest" priority is removed. By default the sort order is +# from highest to lowest, but a lowest-to-highest sort order can be +# set on construction. +# +# The API is based on the `Queue` class from the Ruby standard library. +# +# The pure Ruby implementation, `RubyNonConcurrentPriorityQueue` uses a heap algorithm +# stored in an array. The algorithm is based on the work of Robert Sedgewick +# and Kevin Wayne. +# +# The JRuby native implementation is a thin wrapper around the standard +# library `java.util.NonConcurrentPriorityQueue`. +# +# When running under JRuby the class `NonConcurrentPriorityQueue` extends `JavaNonConcurrentPriorityQueue`. +# When running under all other interpreters it extends `RubyNonConcurrentPriorityQueue`. +# +# @note This implementation is *not* thread safe. +# @see http://en.wikipedia.org/wiki/Priority_queue +# @see http://ruby-doc.org/stdlib-2.0.0/libdoc/thread/rdoc/Queue.html +# @see http://algs4.cs.princeton.edu/24pq/index.php#2.6 +# @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html +# @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#8 +class Concurrent::Collection::RubyNonConcurrentPriorityQueue + # Create a new priority queue with no items. + # + # @option opts + # @param opts [Hash] the options for creating the queue + # @return [RubyNonConcurrentPriorityQueue] a new instance of RubyNonConcurrentPriorityQueue + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#11 + def initialize(opts = T.unsafe(nil)); end + + # Inserts the specified element into this priority queue. + # + # @param item [Object] the item to insert onto the queue + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def <<(item); end + + # Removes all of the elements from this priority queue. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#18 + def clear; end + + # Deletes all items from `self` that are equal to `item`. + # + # @param item [Object] the item to be removed from the queue + # @return [Object] true if the item is found else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#25 + def delete(item); end + + # Retrieves and removes the head of this queue, or returns `nil` if this + # queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def deq; end + + # Returns `true` if `self` contains no elements. + # + # @return [Boolean] true if there are no items in the queue else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#43 + def empty?; end + + # Inserts the specified element into this priority queue. + # + # @param item [Object] the item to insert onto the queue + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def enq(item); end + + # Returns `true` if the given item is present in `self` (that is, if any + # element == `item`), otherwise returns false. + # + # @param item [Object] the item to search for + # @return [Boolean] true if the item is found else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#48 + def has_priority?(item); end + + # Returns `true` if the given item is present in `self` (that is, if any + # element == `item`), otherwise returns false. + # + # @param item [Object] the item to search for + # @return [Boolean] true if the item is found else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#48 + def include?(item); end + + # The current length of the queue. + # + # @return [Fixnum] the number of items in the queue + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#54 + def length; end + + # Retrieves, but does not remove, the head of this queue, or returns `nil` + # if this queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#60 + def peek; end + + # Retrieves and removes the head of this queue, or returns `nil` if this + # queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def pop; end + + # Inserts the specified element into this priority queue. + # + # @param item [Object] the item to insert onto the queue + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#78 + def push(item); end + + # Retrieves and removes the head of this queue, or returns `nil` if this + # queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#65 + def shift; end + + # The current length of the queue. + # + # @return [Fixnum] the number of items in the queue + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#54 + def size; end + + private + + # Are the items at the given indexes ordered based on the priority + # order specified at construction? + # + # @param x [Integer] the first index from which to retrieve a comparable value + # @param y [Integer] the second index from which to retrieve a comparable value + # @return [Boolean] true if the two elements are in the correct priority order + # else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#119 + def ordered?(x, y); end + + # Percolate down to maintain heap invariant. + # + # @param k [Integer] the index at which to start the percolation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#128 + def sink(k); end + + # Exchange the values at the given indexes within the internal array. + # + # @param x [Integer] the first index to swap + # @param y [Integer] the second index to swap + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#103 + def swap(x, y); end + + # Percolate up to maintain heap invariant. + # + # @param k [Integer] the index at which to start the percolation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#147 + def swim(k); end + + class << self + # @!macro priority_queue_method_from_list + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb#89 + def from_list(list, opts = T.unsafe(nil)); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#2 +module Concurrent::Concern; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/deprecation.rb#8 +module Concurrent::Concern::Deprecation + include ::Logger::Severity + include ::Concurrent::Concern::Logging + extend ::Logger::Severity + extend ::Concurrent::Concern::Logging + extend ::Concurrent::Concern::Deprecation + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/deprecation.rb#12 + def deprecated(message, strip = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/deprecation.rb#27 + def deprecated_method(old_name, new_name); end +end + +# Object references in Ruby are mutable. This can lead to serious problems when +# the `#value` of a concurrent object is a mutable reference. Which is always the +# case unless the value is a `Fixnum`, `Symbol`, or similar "primitive" data type. +# Most classes in this library that expose a `#value` getter method do so using the +# `Dereferenceable` mixin module. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#11 +module Concurrent::Concern::Dereferenceable + # Return the value this object represents after applying the options specified + # by the `#set_deref_options` method. + # + # @return [Object] the current value of the object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#21 + def deref; end + + # Return the value this object represents after applying the options specified + # by the `#set_deref_options` method. + # + # @return [Object] the current value of the object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#21 + def value; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#63 + def apply_deref_options(value); end + + # Set the options which define the operations #value performs before + # returning data to the caller (dereferencing). + # + # @note Most classes that include this module will call `#set_deref_options` + # from within the constructor, thus allowing these options to be set at + # object creation. + # @option opts + # @option opts + # @option opts + # @param opts [Hash] the options defining dereference behavior. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#54 + def ns_set_deref_options(opts); end + + # Set the options which define the operations #value performs before + # returning data to the caller (dereferencing). + # + # @note Most classes that include this module will call `#set_deref_options` + # from within the constructor, thus allowing these options to be set at + # object creation. + # @option opts + # @option opts + # @option opts + # @param opts [Hash] the options defining dereference behavior. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#48 + def set_deref_options(opts = T.unsafe(nil)); end + + # Set the internal value of this object + # + # @param value [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/dereferenceable.rb#31 + def value=(value); end +end + +# Include where logging is needed +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#10 +module Concurrent::Concern::Logging + include ::Logger::Severity + + # Logs through {Concurrent.global_logger}, it can be overridden by setting @logger + # + # @param level [Integer] one of Logger::Severity constants + # @param progname [String] e.g. a path of an Actor + # @param message [String, nil] when nil block is used to generate the message + # @yieldreturn [String] a message + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#18 + def log(level, progname, message = T.unsafe(nil), &block); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#10 +module Concurrent::Concern::Obligation + include ::Concurrent::Concern::Dereferenceable + + # Has the obligation completed processing? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#49 + def complete?; end + + # @example allows Obligation to be risen + # rejected_ivar = Ivar.new.fail + # raise rejected_ivar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#126 + def exception(*args); end + + # Has the obligation been fulfilled? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#20 + def fulfilled?; end + + # Is the obligation still awaiting completion of processing? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#56 + def incomplete?; end + + # Wait until obligation is complete or the timeout is reached. Will re-raise + # any exceptions raised during processing (but will not raise an exception + # on timeout). + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @raise [Exception] raises the reason when rejected + # @return [Obligation] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#86 + def no_error!(timeout = T.unsafe(nil)); end + + # Is obligation completion still pending? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#35 + def pending?; end + + # Has the obligation been fulfilled? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#20 + def realized?; end + + # If an exception was raised during processing this will return the + # exception object. Will return `nil` when the state is pending or if + # the obligation has been successfully fulfilled. + # + # @return [Exception] the exception raised during processing or `nil` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#119 + def reason; end + + # Has the obligation been rejected? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#28 + def rejected?; end + + # The current state of the obligation. + # + # @return [Symbol] the current state + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#110 + def state; end + + # Is the obligation still unscheduled? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#42 + def unscheduled?; end + + # The current value of the obligation. Will be `nil` while the state is + # pending or the operation has been rejected. + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @return [Object] see Dereferenceable#deref + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#65 + def value(timeout = T.unsafe(nil)); end + + # The current value of the obligation. Will be `nil` while the state is + # pending or the operation has been rejected. Will re-raise any exceptions + # raised during processing (but will not raise an exception on timeout). + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @raise [Exception] raises the reason when rejected + # @return [Object] see Dereferenceable#deref + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#98 + def value!(timeout = T.unsafe(nil)); end + + # Wait until obligation is complete or the timeout has been reached. + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @return [Obligation] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#74 + def wait(timeout = T.unsafe(nil)); end + + # Wait until obligation is complete or the timeout is reached. Will re-raise + # any exceptions raised during processing (but will not raise an exception + # on timeout). + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @raise [Exception] raises the reason when rejected + # @return [Obligation] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#86 + def wait!(timeout = T.unsafe(nil)); end + + protected + + # Atomic compare and set operation + # State is set to `next_state` only if `current state == expected_current`. + # + # @param next_state [Symbol] + # @param expected_current [Symbol] + # @return [Boolean] true is state is changed, false otherwise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#174 + def compare_and_set_state(next_state, *expected_current); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#145 + def event; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#134 + def get_arguments_from(opts = T.unsafe(nil)); end + + # Executes the block within mutex if current state is included in expected_states + # + # @return block value if executed, false otherwise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#190 + def if_state(*expected_states); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#139 + def init_obligation; end + + # Am I in the current state? + # + # @param expected [Symbol] The state to check against + # @return [Boolean] true if in the expected state else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#210 + def ns_check_state?(expected); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#215 + def ns_set_state(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#150 + def set_state(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/obligation.rb#161 + def state=(value); end +end + +# The [observer pattern](http://en.wikipedia.org/wiki/Observer_pattern) is one +# of the most useful design patterns. +# +# The workflow is very simple: +# - an `observer` can register itself to a `subject` via a callback +# - many `observers` can be registered to the same `subject` +# - the `subject` notifies all registered observers when its status changes +# - an `observer` can deregister itself when is no more interested to receive +# event notifications +# +# In a single threaded environment the whole pattern is very easy: the +# `subject` can use a simple data structure to manage all its subscribed +# `observer`s and every `observer` can react directly to every event without +# caring about synchronization. +# +# In a multi threaded environment things are more complex. The `subject` must +# synchronize the access to its data structure and to do so currently we're +# using two specialized ObserverSet: {Concurrent::Concern::CopyOnWriteObserverSet} +# and {Concurrent::Concern::CopyOnNotifyObserverSet}. +# +# When implementing and `observer` there's a very important rule to remember: +# **there are no guarantees about the thread that will execute the callback** +# +# Let's take this example +# ``` +# class Observer +# def initialize +# @count = 0 +# end +# +# def update +# @count += 1 +# end +# end +# +# obs = Observer.new +# [obj1, obj2, obj3, obj4].each { |o| o.add_observer(obs) } +# # execute [obj1, obj2, obj3, obj4] +# ``` +# +# `obs` is wrong because the variable `@count` can be accessed by different +# threads at the same time, so it should be synchronized (using either a Mutex +# or an AtomicFixum) +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#50 +module Concurrent::Concern::Observable + # Adds an observer to this set. If a block is passed, the observer will be + # created by this method and no other params should be passed. + # + # @param observer [Object] the observer to add + # @param func [Symbol] the function to call on the observer during notification. + # Default is :update + # @return [Object] the added observer + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#61 + def add_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + # Return the number of observers associated with this object. + # + # @return [Integer] the observers count + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#101 + def count_observers; end + + # Remove `observer` as an observer on this object so that it will no + # longer receive notifications. + # + # @param observer [Object] the observer to remove + # @return [Object] the deleted observer + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#82 + def delete_observer(observer); end + + # Remove all observers associated with this object. + # + # @return [Observable] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#91 + def delete_observers; end + + # As `#add_observer` but can be used for chaining. + # + # @param observer [Object] the observer to add + # @param func [Symbol] the function to call on the observer during notification. + # @return [Observable] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#70 + def with_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + protected + + # Returns the value of attribute observers. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#107 + def observers; end + + # Sets the attribute observers + # + # @param value the value to set the attribute observers to. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/observable.rb#107 + def observers=(_arg0); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#70 +class Concurrent::ConcurrentUpdateError < ::ThreadError; end + +# frozen pre-allocated backtrace to speed ConcurrentUpdateError +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#72 +Concurrent::ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE = T.let(T.unsafe(nil), Array) + +# Raised when errors occur during configuration. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#6 +class Concurrent::ConfigurationError < ::Concurrent::Error; end + +# A synchronization object that allows one thread to wait on multiple other threads. +# The thread that will wait creates a `CountDownLatch` and sets the initial value +# (normally equal to the number of other threads). The initiating thread passes the +# latch to the other threads then waits for the other threads by calling the `#wait` +# method. Each of the other threads calls `#count_down` when done with its work. +# When the latch counter reaches zero the waiting thread is unblocked and continues +# with its work. A `CountDownLatch` can be used only once. Its value cannot be reset. +# +# @example Waiter and Decrementer +# latch = Concurrent::CountDownLatch.new(3) +# +# waiter = Thread.new do +# latch.wait() +# puts ("Waiter released") +# end +# +# decrementer = Thread.new do +# sleep(1) +# latch.count_down +# puts latch.count +# +# sleep(1) +# latch.count_down +# puts latch.count +# +# sleep(1) +# latch.count_down +# puts latch.count +# end +# +# [waiter, decrementer].each(&:join) +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb#98 +class Concurrent::CountDownLatch < ::Concurrent::MutexCountDownLatch; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb#56 +Concurrent::CountDownLatchImplementation = Concurrent::MutexCountDownLatch + +# A synchronization aid that allows a set of threads to all wait for each +# other to reach a common barrier point. +# +# @example +# barrier = Concurrent::CyclicBarrier.new(3) +# jobs = Array.new(3) { |i| -> { sleep i; p done: i } } +# process = -> (i) do +# # waiting to start at the same time +# barrier.wait +# # execute job +# jobs[i].call +# # wait for others to finish +# barrier.wait +# end +# threads = 2.times.map do |i| +# Thread.new(i, &process) +# end +# +# # use main as well +# process.call 2 +# +# # here we can be sure that all jobs are processed +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#27 +class Concurrent::CyclicBarrier < ::Concurrent::Synchronization::LockableObject + # Create a new `CyclicBarrier` that waits for `parties` threads + # + # @param parties [Fixnum] the number of parties + # @raise [ArgumentError] if `parties` is not an integer or is less than zero + # @return [CyclicBarrier] a new instance of CyclicBarrier + # @yield an optional block that will be executed that will be executed after + # the last thread arrives and before the others are released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#40 + def initialize(parties, &block); end + + # A barrier can be broken when: + # - a thread called the `reset` method while at least one other thread was waiting + # - at least one thread timed out on `wait` method + # + # A broken barrier can be restored using `reset` it's safer to create a new one + # + # @return [Boolean] true if the barrier is broken otherwise false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#105 + def broken?; end + + # @return [Fixnum] the number of threads currently waiting on the barrier + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#54 + def number_waiting; end + + # @return [Fixnum] the number of threads needed to pass the barrier + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#49 + def parties; end + + # resets the barrier to its initial state + # If there is at least one waiting thread, it will be woken up, the `wait` + # method will return false and the barrier will be broken + # If the barrier is broken, this method restores it to the original state + # + # @return [nil] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#95 + def reset; end + + # Blocks on the barrier until the number of waiting threads is equal to + # `parties` or until `timeout` is reached or `reset` is called + # If a block has been passed to the constructor, it will be executed once by + # the last arrived thread before releasing the others + # + # @param timeout [Fixnum] the number of seconds to wait for the counter or + # `nil` to block indefinitely + # @return [Boolean] `true` if the `count` reaches zero else false on + # `timeout` or on `reset` or if the barrier is broken + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#66 + def wait(timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#111 + def ns_generation_done(generation, status, continue = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#122 + def ns_initialize(parties, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#117 + def ns_next_generation; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb#30 +class Concurrent::CyclicBarrier::Generation < ::Struct + # Returns the value of attribute status + # + # @return [Object] the current value of status + def status; end + + # Sets the attribute status + # + # @param value [Object] the value to set the attribute status to. + # @return [Object] the newly set value + def status=(_); end + + class << self + def [](*_arg0); end + def inspect; end + def keyword_init?; end + def members; end + def new(*_arg0); end + end +end + +# Lazy evaluation of a block yielding an immutable result. Useful for +# expensive operations that may never be needed. It may be non-blocking, +# supports the `Concern::Obligation` interface, and accepts the injection of +# custom executor upon which to execute the block. Processing of +# block will be deferred until the first time `#value` is called. +# At that time the caller can choose to return immediately and let +# the block execute asynchronously, block indefinitely, or block +# with a timeout. +# +# When a `Delay` is created its state is set to `pending`. The value and +# reason are both `nil`. The first time the `#value` method is called the +# enclosed opration will be run and the calling thread will block. Other +# threads attempting to call `#value` will block as well. Once the operation +# is complete the *value* will be set to the result of the operation or the +# *reason* will be set to the raised exception, as appropriate. All threads +# blocked on `#value` will return. Subsequent calls to `#value` will immediately +# return the cached value. The operation will only be run once. This means that +# any side effects created by the operation will only happen once as well. +# +# `Delay` includes the `Concurrent::Concern::Dereferenceable` mixin to support thread +# safety of the reference returned by `#value`. +# +# @note The default behavior of `Delay` is to block indefinitely when +# calling either `value` or `wait`, executing the delayed operation on +# the current thread. This makes the `timeout` value completely +# irrelevant. To enable non-blocking behavior, use the `executor` +# constructor option. This will cause the delayed operation to be +# execute on the given executor, allowing the call to timeout. +# @see Concurrent::Concern::Dereferenceable +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#44 +class Concurrent::Delay < ::Concurrent::Synchronization::LockableObject + include ::Concurrent::Concern::Dereferenceable + include ::Concurrent::Concern::Obligation + + # Create a new `Delay` in the `:pending` state. + # + # @raise [ArgumentError] if no block is given + # @return [Delay] a new instance of Delay + # @yield the delayed operation to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#62 + def initialize(opts = T.unsafe(nil), &block); end + + # Reconfigures the block returning the value if still `#incomplete?` + # + # @return [true, false] if success + # @yield the delayed operation to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#146 + def reconfigure(&block); end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. If the delayed operation + # raised an exception this method will return nil. The exception object + # can be accessed via the `#reason` method. + # + # @note The default behavior of `Delay` is to block indefinitely when + # calling either `value` or `wait`, executing the delayed operation on + # the current thread. This makes the `timeout` value completely + # irrelevant. To enable non-blocking behavior, use the `executor` + # constructor option. This will cause the delayed operation to be + # execute on the given executor, allowing the call to timeout. + # @param timeout [Numeric] the maximum number of seconds to wait + # @return [Object] the current value of the object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#77 + def value(timeout = T.unsafe(nil)); end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. If the delayed operation + # raised an exception, this method will raise that exception (even when) + # the operation has already been executed). + # + # @note The default behavior of `Delay` is to block indefinitely when + # calling either `value` or `wait`, executing the delayed operation on + # the current thread. This makes the `timeout` value completely + # irrelevant. To enable non-blocking behavior, use the `executor` + # constructor option. This will cause the delayed operation to be + # execute on the given executor, allowing the call to timeout. + # @param timeout [Numeric] the maximum number of seconds to wait + # @raise [Exception] when `#rejected?` raises `#reason` + # @return [Object] the current value of the object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#113 + def value!(timeout = T.unsafe(nil)); end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. + # + # @note The default behavior of `Delay` is to block indefinitely when + # calling either `value` or `wait`, executing the delayed operation on + # the current thread. This makes the `timeout` value completely + # irrelevant. To enable non-blocking behavior, use the `executor` + # constructor option. This will cause the delayed operation to be + # execute on the given executor, allowing the call to timeout. + # @param timeout [Integer] (nil) the maximum number of seconds to wait for + # the value to be computed. When `nil` the caller will block indefinitely. + # @return [Object] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#132 + def wait(timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#160 + def ns_initialize(opts, &block); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/delay.rb#173 + def execute_task_once; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#7 +class Concurrent::DependencyCounter + # @return [DependencyCounter] a new instance of DependencyCounter + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#9 + def initialize(count, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/dataflow.rb#14 + def update(time, value, reason); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#3 +class Concurrent::Error < ::StandardError; end + +# Old school kernel-style event reminiscent of Win32 programming in C++. +# +# When an `Event` is created it is in the `unset` state. Threads can choose to +# `#wait` on the event, blocking until released by another thread. When one +# thread wants to alert all blocking threads it calls the `#set` method which +# will then wake up all listeners. Once an `Event` has been set it remains set. +# New threads calling `#wait` will return immediately. An `Event` may be +# `#reset` at any time once it has been set. +# +# @example +# event = Concurrent::Event.new +# +# t1 = Thread.new do +# puts "t1 is waiting" +# event.wait(1) +# puts "event occurred" +# end +# +# t2 = Thread.new do +# puts "t2 calling set" +# event.set +# end +# +# [t1, t2].each(&:join) +# +# # prints: +# # t1 is waiting +# # t2 calling set +# # event occurred +# @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#36 +class Concurrent::Event < ::Concurrent::Synchronization::LockableObject + # Creates a new `Event` in the unset state. Threads calling `#wait` on the + # `Event` will block. + # + # @return [Event] a new instance of Event + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#40 + def initialize; end + + # Reset a previously set event back to the `unset` state. + # Has no effect if the `Event` has not yet been set. + # + # @return [Boolean] should always return `true` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#68 + def reset; end + + # Trigger the event, setting the state to `set` and releasing all threads + # waiting on the event. Has no effect if the `Event` has already been set. + # + # @return [Boolean] should always return `true` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#56 + def set; end + + # Is the object in the set state? + # + # @return [Boolean] indicating whether or not the `Event` has been set + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#48 + def set?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#60 + def try?; end + + # Wait a given number of seconds for the `Event` to be set by another + # thread. Will wait forever when no `timeout` value is given. Returns + # immediately if the `Event` has already been set. + # + # @return [Boolean] true if the `Event` was set before timeout else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#83 + def wait(timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#104 + def ns_initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/event.rb#96 + def ns_set; end +end + +# A synchronization point at which threads can pair and swap elements within +# pairs. Each thread presents some object on entry to the exchange method, +# matches with a partner thread, and receives its partner's object on return. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# This implementation is very simple, using only a single slot for each +# exchanger (unlike more advanced implementations which use an "arena"). +# This approach will work perfectly fine when there are only a few threads +# accessing a single `Exchanger`. Beyond a handful of threads the performance +# will degrade rapidly due to contention on the single slot, but the algorithm +# will remain correct. +# +# @example +# +# exchanger = Concurrent::Exchanger.new +# +# threads = [ +# Thread.new { puts "first: " << exchanger.exchange('foo', 1) }, #=> "first: bar" +# Thread.new { puts "second: " << exchanger.exchange('bar', 1) } #=> "second: foo" +# ] +# threads.each {|t| t.join(2) } +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html java.util.concurrent.Exchanger +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#336 +class Concurrent::Exchanger < ::Concurrent::RubyExchanger; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#327 +Concurrent::ExchangerImplementation = Concurrent::RubyExchanger + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#157 +module Concurrent::ExecutorService + include ::Logger::Severity + include ::Concurrent::Concern::Logging + + # Submit a task to the executor for asynchronous processing. + # + # @param task [Proc] the asynchronous task to perform + # @return [self] returns itself + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#166 + def <<(task); end + + # Does the task queue have a maximum size? + # + # @note Always returns `false` + # @return [Boolean] True if the task queue has a maximum size else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#174 + def can_overflow?; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#161 + def post(*args, &task); end + + # Does this executor guarantee serialization of its operations? + # + # @note Always returns `false` + # @return [Boolean] True if the executor guarantees that all operations + # will be post in the order they are received and no two operations may + # occur simultaneously. Else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#181 + def serialized?; end +end + +# A `FiberLocalVar` is a variable where the value is different for each fiber. +# Each variable may have a default value, but when you modify the variable only +# the current fiber will ever see that change. +# +# This is similar to Ruby's built-in fiber-local variables (`Thread.current[:name]`), +# but with these major advantages: +# * `FiberLocalVar` has its own identity, it doesn't need a Symbol. +# * Each Ruby's built-in fiber-local variable leaks some memory forever (it's a Symbol held forever on the fiber), +# so it's only OK to create a small amount of them. +# `FiberLocalVar` has no such issue and it is fine to create many of them. +# * Ruby's built-in fiber-local variables leak forever the value set on each fiber (unless set to nil explicitly). +# `FiberLocalVar` automatically removes the mapping for each fiber once the `FiberLocalVar` instance is GC'd. +# +# @example +# v = FiberLocalVar.new(14) +# v.value #=> 14 +# v.value = 2 +# v.value #=> 2 +# @example +# v = FiberLocalVar.new(14) +# +# Fiber.new do +# v.value #=> 14 +# v.value = 1 +# v.value #=> 1 +# end.resume +# +# Fiber.new do +# v.value #=> 14 +# v.value = 2 +# v.value #=> 2 +# end.resume +# +# v.value #=> 14 +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#41 +class Concurrent::FiberLocalVar + # Creates a fiber local variable. + # + # @param default [Object] the default value when otherwise unset + # @param default_block [Proc] Optional block that gets called to obtain the + # default value for each fiber + # @return [FiberLocalVar] a new instance of FiberLocalVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#49 + def initialize(default = T.unsafe(nil), &default_block); end + + # Bind the given value to fiber local storage during + # execution of the given block. + # + # @param value [Object] the value to bind + # @return [Object] the value + # @yield the operation to be performed with the bound variable + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#86 + def bind(value); end + + # Returns the value in the current fiber's copy of this fiber-local variable. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#68 + def value; end + + # Sets the current fiber's copy of this fiber-local variable to the specified value. + # + # @param value [Object] the value to set + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#76 + def value=(value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#101 + def default; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb#42 +Concurrent::FiberLocalVar::LOCALS = T.let(T.unsafe(nil), Concurrent::FiberLocals) + +# An array-backed storage of indexed variables per fiber. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#166 +class Concurrent::FiberLocals < ::Concurrent::AbstractLocals + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#167 + def locals; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#171 + def locals!; end +end + +# A thread pool that reuses a fixed number of threads operating off an unbounded queue. +# At any point, at most `num_threads` will be active processing tasks. When all threads are busy new +# tasks `#post` to the thread pool are enqueued until a thread becomes available. +# Should a thread crash for any reason the thread will immediately be removed +# from the pool and replaced. +# +# The API and behavior of this class are based on Java's `FixedThreadPool` +# +# **Thread Pool Options** +# +# Thread pools support several configuration options: +# +# * `idletime`: The number of seconds that a thread may be idle before being reclaimed. +# * `name`: The name of the executor (optional). Printed in the executor's `#to_s` output and +# a `-worker-` name is given to its threads if supported by used Ruby +# implementation. `` is uniq for each thread. +# * `max_queue`: The maximum number of tasks that may be waiting in the work queue at +# any one time. When the queue size reaches `max_queue` and no new threads can be created, +# subsequent tasks will be rejected in accordance with the configured `fallback_policy`. +# * `auto_terminate`: When true (default), the threads started will be marked as daemon. +# * `fallback_policy`: The policy defining how rejected tasks are handled. +# +# Three fallback policies are supported: +# +# * `:abort`: Raise a `RejectedExecutionError` exception and discard the task. +# * `:discard`: Discard the task and return false. +# * `:caller_runs`: Execute the task on the calling thread. +# +# **Shutting Down Thread Pools** +# +# Killing a thread pool while tasks are still being processed, either by calling +# the `#kill` method or at application exit, will have unpredictable results. There +# is no way for the thread pool to know what resources are being used by the +# in-progress tasks. When those tasks are killed the impact on those resources +# cannot be predicted. The *best* practice is to explicitly shutdown all thread +# pools using the provided methods: +# +# * Call `#shutdown` to initiate an orderly termination of all in-progress tasks +# * Call `#wait_for_termination` with an appropriate timeout interval an allow +# the orderly shutdown to complete +# * Call `#kill` *only when* the thread pool fails to shutdown in the allotted time +# +# On some runtime platforms (most notably the JVM) the application will not +# exit until all thread pools have been shutdown. To prevent applications from +# "hanging" on exit, all threads can be marked as daemon according to the +# `:auto_terminate` option. +# +# ```ruby +# pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon +# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon +# ``` +# +# @note Failure to properly shutdown a thread pool can lead to unpredictable results. +# Please read *Shutting Down Thread Pools* for more information. +# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface +# @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean- +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb#201 +class Concurrent::FixedThreadPool < ::Concurrent::ThreadPoolExecutor + # Create a new thread pool. + # + # @option opts + # @param num_threads [Integer] the number of threads to allocate + # @param opts [Hash] the options defining pool behavior. + # @raise [ArgumentError] if `num_threads` is less than or equal to zero + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # @return [FixedThreadPool] a new instance of FixedThreadPool + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int- + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb#215 + def initialize(num_threads, opts = T.unsafe(nil)); end +end + +# {include:file:docs-source/future.md} +# +# @see http://ruby-doc.org/stdlib-2.1.1/libdoc/observer/rdoc/Observable.html Ruby Observable module +# @see http://clojuredocs.org/clojure_core/clojure.core/future Clojure's future function +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html java.util.concurrent.Future +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#21 +class Concurrent::Future < ::Concurrent::IVar + # Create a new `Future` in the `:unscheduled` state. + # + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Future] a new instance of Future + # @yield the asynchronous operation to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#33 + def initialize(opts = T.unsafe(nil), &block); end + + # Attempt to cancel the operation if it has not already processed. + # The operation can only be cancelled while still `pending`. It cannot + # be cancelled once it has begun processing or has completed. + # + # @return [Boolean] was the operation successfully cancelled. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#99 + def cancel; end + + # Has the operation been successfully cancelled? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#111 + def cancelled?; end + + # Execute an `:unscheduled` `Future`. Immediately sets the state to `:pending` and + # passes the block to a new thread/thread pool for eventual execution. + # Does nothing if the `Future` is in any state other than `:unscheduled`. + # + # @example Instance and execute in separate steps + # future = Concurrent::Future.new{ sleep(1); 42 } + # future.state #=> :unscheduled + # future.execute + # future.state #=> :pending + # @example Instance and execute in one line + # future = Concurrent::Future.new{ sleep(1); 42 }.execute + # future.state #=> :pending + # @return [Future] a reference to `self` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#53 + def execute; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#82 + def set(value = T.unsafe(nil), &block); end + + # Wait the given number of seconds for the operation to complete. + # On timeout attempt to cancel the operation. + # + # @param timeout [Numeric] the maximum time in seconds to wait. + # @return [Boolean] true if the operation completed before the timeout + # else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#121 + def wait_or_cancel(timeout); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#133 + def ns_initialize(value, opts); end + + class << self + # Create a new `Future` object with the given block, execute it, and return the + # `:pending` object. + # + # @example + # future = Concurrent::Future.execute{ sleep(1); 42 } + # future.state #=> :pending + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Future] the newly created `Future` in the `:pending` state + # @yield the asynchronous operation to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/future.rb#77 + def execute(opts = T.unsafe(nil), &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#18 +Concurrent::GLOBAL_FAST_EXECUTOR = T.let(T.unsafe(nil), Concurrent::Delay) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#30 +Concurrent::GLOBAL_IMMEDIATE_EXECUTOR = T.let(T.unsafe(nil), Concurrent::ImmediateExecutor) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#22 +Concurrent::GLOBAL_IO_EXECUTOR = T.let(T.unsafe(nil), Concurrent::Delay) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#106 +Concurrent::GLOBAL_LOGGER = T.let(T.unsafe(nil), Concurrent::AtomicReference) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/configuration.rb#26 +Concurrent::GLOBAL_TIMER_SET = T.let(T.unsafe(nil), Concurrent::Delay) + +# A thread-safe subclass of Hash. This version locks against the object +# itself for every method call, ensuring only one thread can be reading +# or writing at a time. This includes iteration methods like `#each`, +# which takes the lock repeatedly when reading an item. +# +# @see http://ruby-doc.org/core/Hash.html Ruby standard library `Hash` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/hash.rb#49 +class Concurrent::Hash < ::Hash; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/hash.rb#16 +Concurrent::HashImplementation = Hash + +# An `IVar` is like a future that you can assign. As a future is a value that +# is being computed that you can wait on, an `IVar` is a value that is waiting +# to be assigned, that you can wait on. `IVars` are single assignment and +# deterministic. +# +# Then, express futures as an asynchronous computation that assigns an `IVar`. +# The `IVar` becomes the primitive on which [futures](Future) and +# [dataflow](Dataflow) are built. +# +# An `IVar` is a single-element container that is normally created empty, and +# can only be set once. The I in `IVar` stands for immutable. Reading an +# `IVar` normally blocks until it is set. It is safe to set and read an `IVar` +# from different threads. +# +# If you want to have some parallel task set the value in an `IVar`, you want +# a `Future`. If you want to create a graph of parallel tasks all executed +# when the values they depend on are ready you want `dataflow`. `IVar` is +# generally a low-level primitive. +# +# ## Examples +# +# Create, set and get an `IVar` +# +# ```ruby +# ivar = Concurrent::IVar.new +# ivar.set 14 +# ivar.value #=> 14 +# ivar.set 2 # would now be an error +# ``` +# +# ## See Also +# +# 1. For the theory: Arvind, R. Nikhil, and K. Pingali. +# [I-Structures: Data structures for parallel computing](http://dl.acm.org/citation.cfm?id=69562). +# In Proceedings of Workshop on Graph Reduction, 1986. +# 2. For recent application: +# [DataDrivenFuture in Habanero Java from Rice](http://www.cs.rice.edu/~vs3/hjlib/doc/edu/rice/hj/api/HjDataDrivenFuture.html). +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#48 +class Concurrent::IVar < ::Concurrent::Synchronization::LockableObject + include ::Concurrent::Concern::Dereferenceable + include ::Concurrent::Concern::Obligation + include ::Concurrent::Concern::Observable + + # Create a new `IVar` in the `:pending` state with the (optional) initial value. + # + # @option opts + # @option opts + # @option opts + # @param value [Object] the initial value + # @param opts [Hash] the options to create a message with + # @return [IVar] a new instance of IVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#62 + def initialize(value = T.unsafe(nil), opts = T.unsafe(nil), &block); end + + # Add an observer on this object that will receive notification on update. + # + # Upon completion the `IVar` will notify all observers in a thread-safe way. + # The `func` method of the observer will be called with three arguments: the + # `Time` at which the `Future` completed the asynchronous operation, the + # final `value` (or `nil` on rejection), and the final `reason` (or `nil` on + # fulfillment). + # + # @param observer [Object] the object that will be notified of changes + # @param func [Symbol] symbol naming the method to call when this + # `Observable` has changes` + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#81 + def add_observer(observer = T.unsafe(nil), func = T.unsafe(nil), &block); end + + # Set the `IVar` to failed due to some error and wake or notify all threads waiting on it. + # + # @param reason [Object] for the failure + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @return [IVar] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#135 + def fail(reason = T.unsafe(nil)); end + + # Set the `IVar` to a value and wake or notify all threads waiting on it. + # + # @param value [Object] the value to store in the `IVar` + # @raise [ArgumentError] if both a value and a block are given + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @return [IVar] self + # @yield A block operation to use for setting the value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#113 + def set(value = T.unsafe(nil)); end + + # Attempt to set the `IVar` with the given value or block. Return a + # boolean indicating the success or failure of the set operation. + # + # @param value [Object] the value to store in the `IVar` + # @raise [ArgumentError] if both a value and a block are given + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @return [Boolean] true if the value was set else false + # @yield A block operation to use for setting the value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#145 + def try_set(value = T.unsafe(nil), &block); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#202 + def check_for_block_or_value!(block_given, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#177 + def complete(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#184 + def complete_without_notification(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#190 + def notify_observers(value, reason); end + + # @raise [MultipleAssignmentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#195 + def ns_complete_without_notification(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#155 + def ns_initialize(value, opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#168 + def safe_execute(task, args = T.unsafe(nil)); end +end + +# Raised when an operation is attempted which is not legal given the +# receiver's current state +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#20 +class Concurrent::IllegalOperationError < ::Concurrent::Error; end + +# An executor service which runs all operations on the current thread, +# blocking as necessary. Operations are performed in the order they are +# received and no two operations can be performed simultaneously. +# +# This executor service exists mainly for testing an debugging. When used +# it immediately runs every `#post` operation on the current thread, blocking +# that thread until the operation is complete. This can be very beneficial +# during testing because it makes all operations deterministic. +# +# @note Intended for use primarily in testing and debugging. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#17 +class Concurrent::ImmediateExecutor < ::Concurrent::AbstractExecutorService + include ::Concurrent::SerialExecutorService + + # Creates a new executor + # + # @return [ImmediateExecutor] a new instance of ImmediateExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#21 + def initialize; end + + # Submit a task to the executor for asynchronous processing. + # + # @param task [Proc] the asynchronous task to perform + # @return [self] returns itself + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#34 + def <<(task); end + + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#55 + def kill; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#26 + def post(*args, &task); end + + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#40 + def running?; end + + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#55 + def shutdown; end + + # Is the executor shutdown? + # + # @return [Boolean] `true` when shutdown, `false` when shutting down or running + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#50 + def shutdown?; end + + # Is the executor shuttingdown? + # + # @return [Boolean] `true` when not running and not shutdown, else `false` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#45 + def shuttingdown?; end + + # Block until executor shutdown is complete or until `timeout` seconds have + # passed. + # + # @note Does not initiate shutdown or termination. Either `shutdown` or `kill` + # must be called before this method (or on another thread). + # @param timeout [Integer] the maximum number of seconds to wait for shutdown to complete + # @return [Boolean] `true` if shutdown complete or false on `timeout` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/immediate_executor.rb#62 + def wait_for_termination(timeout = T.unsafe(nil)); end +end + +# Raised when an attempt is made to violate an immutability guarantee. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#16 +class Concurrent::ImmutabilityError < ::Concurrent::Error; end + +# A thread-safe, immutable variation of Ruby's standard `Struct`. +# +# @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#9 +module Concurrent::ImmutableStruct + include ::Concurrent::Synchronization::AbstractStruct + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#51 + def ==(other); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#46 + def [](member); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#56 + def each(&block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#62 + def each_pair(&block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#29 + def inspect; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#36 + def merge(other, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#68 + def select(&block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#17 + def to_a; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#41 + def to_h; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#29 + def to_s; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#17 + def values; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#24 + def values_at(*indexes); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#76 + def initialize_copy(original); end + + class << self + # @private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#12 + def included(base); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#82 + def new(*args, &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/immutable_struct.rb#92 +Concurrent::ImmutableStruct::FACTORY = T.let(T.unsafe(nil), T.untyped) + +# An executor service which runs all operations on a new thread, blocking +# until it completes. Operations are performed in the order they are received +# and no two operations can be performed simultaneously. +# +# This executor service exists mainly for testing an debugging. When used it +# immediately runs every `#post` operation on a new thread, blocking the +# current thread until the operation is complete. This is similar to how the +# ImmediateExecutor works, but the operation has the full stack of the new +# thread at its disposal. This can be helpful when the operations will spawn +# more operations on the same executor and so on - such a situation might +# overflow the single stack in case of an ImmediateExecutor, which is +# inconsistent with how it would behave for a threaded executor. +# +# @note Intended for use primarily in testing and debugging. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb#19 +class Concurrent::IndirectImmediateExecutor < ::Concurrent::ImmediateExecutor + # Creates a new executor + # + # @return [IndirectImmediateExecutor] a new instance of IndirectImmediateExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb#21 + def initialize; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb#27 + def post(*args, &task); end +end + +# Raised when an object's methods are called when it has not been +# properly initialized. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#24 +class Concurrent::InitializationError < ::Concurrent::Error; end + +# Raised when a lifecycle method (such as `stop`) is called in an improper +# sequence or when the object is in an inappropriate state. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#13 +class Concurrent::LifecycleError < ::Concurrent::Error; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#6 +class Concurrent::LockFreeStack < ::Concurrent::Synchronization::Object + include ::Enumerable + extend ::Concurrent::Synchronization::SafeInitialization + + # @param head [Node] + # @return [LockFreeStack] a new instance of LockFreeStack + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#51 + def initialize(head = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#118 + def clear; end + + # @return [self] + # @yield over the cleared stack + # @yieldparam value [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#142 + def clear_each(&block); end + + # @param head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#128 + def clear_if(head); end + + # @param head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#99 + def compare_and_clear(head); end + + # @param head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#85 + def compare_and_pop(head); end + + # @param head [Node] + # @param value [Object] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#65 + def compare_and_push(head, value); end + + # @param head [Node] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#107 + def each(head = T.unsafe(nil)); end + + # @param head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#58 + def empty?(head = T.unsafe(nil)); end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#154 + def inspect; end + + # @return [Node] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#79 + def peek; end + + # @return [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#90 + def pop; end + + # @param value [Object] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#71 + def push(value); end + + # @param head [Node] + # @param new_head [Node] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#135 + def replace_if(head, new_head); end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#154 + def to_s; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_head(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def head; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def head=(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_head(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_head(&block); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#41 + def of1(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#46 + def of2(value1, value2); end + end +end + +# The singleton for empty node +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#32 +Concurrent::LockFreeStack::EMPTY = T.let(T.unsafe(nil), Concurrent::LockFreeStack::Node) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#10 +class Concurrent::LockFreeStack::Node + # @return [Node] a new instance of Node + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#23 + def initialize(value, next_node); end + + # @return [Node] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#14 + def next_node; end + + # @return [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#17 + def value; end + + # allow to nil-ify to free GC when the entry is no longer relevant, not synchronised + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb#21 + def value=(_arg0); end + + class << self + def [](*_arg0); end + end +end + +# Either {FiberLocalVar} or {ThreadLocalVar} depending on whether Mutex (and Monitor) +# are held, respectively, per Fiber or per Thread. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb#21 +Concurrent::LockLocalVar = Concurrent::FiberLocalVar + +# An `MVar` is a synchronized single element container. They are empty or +# contain one item. Taking a value from an empty `MVar` blocks, as does +# putting a value into a full one. You can either think of them as blocking +# queue of length one, or a special kind of mutable variable. +# +# On top of the fundamental `#put` and `#take` operations, we also provide a +# `#mutate` that is atomic with respect to operations on the same instance. +# These operations all support timeouts. +# +# We also support non-blocking operations `#try_put!` and `#try_take!`, a +# `#set!` that ignores existing values, a `#value` that returns the value +# without removing it or returns `MVar::EMPTY`, and a `#modify!` that yields +# `MVar::EMPTY` if the `MVar` is empty and can be used to set `MVar::EMPTY`. +# You shouldn't use these operations in the first instance. +# +# `MVar` is a [Dereferenceable](Dereferenceable). +# +# `MVar` is related to M-structures in Id, `MVar` in Haskell and `SyncVar` in Scala. +# +# Note that unlike the original Haskell paper, our `#take` is blocking. This is how +# Haskell and Scala do it today. +# +# ## See Also +# +# 1. P. Barth, R. Nikhil, and Arvind. [M-Structures: Extending a parallel, non- strict, functional language with state](http://dl.acm.org/citation.cfm?id=652538). In Proceedings of the 5th +# ACM Conference on Functional Programming Languages and Computer Architecture (FPCA), 1991. +# +# 2. S. Peyton Jones, A. Gordon, and S. Finne. [Concurrent Haskell](http://dl.acm.org/citation.cfm?id=237794). +# In Proceedings of the 23rd Symposium on Principles of Programming Languages +# (PoPL), 1996. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#38 +class Concurrent::MVar < ::Concurrent::Synchronization::Object + include ::Concurrent::Concern::Dereferenceable + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `MVar`, either empty or with an initial value. + # + # @param opts [Hash] the options controlling how the future will be processed + # @return [MVar] a new instance of MVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#54 + def initialize(value = T.unsafe(nil), opts = T.unsafe(nil)); end + + # acquires lock on the from an `MVAR`, yields the value to provided block, + # and release lock. A timeout can be set to limit the time spent blocked, + # in which case it returns `TIMEOUT` if the time is exceeded. + # + # @return [Object] the value returned by the block, or `TIMEOUT` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#86 + def borrow(timeout = T.unsafe(nil)); end + + # Returns if the `MVar` is currently empty. + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#195 + def empty?; end + + # Returns if the `MVar` currently contains a value. + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#200 + def full?; end + + # Atomically `take`, yield the value to a block for transformation, and then + # `put` the transformed value. Returns the transformed value. A timeout can + # be set to limit the time spent blocked, in which case it returns `TIMEOUT` + # if the time is exceeded. + # + # @raise [ArgumentError] + # @return [Object] the transformed value, or `TIMEOUT` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#123 + def modify(timeout = T.unsafe(nil)); end + + # Non-blocking version of `modify` that will yield with `EMPTY` if there is no value yet. + # + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#179 + def modify!; end + + # Put a value into an `MVar`, blocking if there is already a value until + # it is empty. A timeout can be set to limit the time spent blocked, in + # which case it returns `TIMEOUT` if the time is exceeded. + # + # @return [Object] the value that was put, or `TIMEOUT` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#103 + def put(value, timeout = T.unsafe(nil)); end + + # Non-blocking version of `put` that will overwrite an existing value. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#169 + def set!(value); end + + # Remove the value from an `MVar`, leaving it empty, and blocking if there + # isn't a value. A timeout can be set to limit the time spent blocked, in + # which case it returns `TIMEOUT` if the time is exceeded. + # + # @return [Object] the value that was taken, or `TIMEOUT` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#66 + def take(timeout = T.unsafe(nil)); end + + # Non-blocking version of `put`, that returns whether or not it was successful. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#156 + def try_put!(value); end + + # Non-blocking version of `take`, that returns `EMPTY` instead of blocking. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#142 + def try_take!; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#206 + def synchronize(&block); end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#212 + def unlocked_empty?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#216 + def unlocked_full?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#224 + def wait_for_empty(timeout); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#220 + def wait_for_full(timeout); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#228 + def wait_while(condition, timeout); end +end + +# Unique value that represents that an `MVar` was empty +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#43 +Concurrent::MVar::EMPTY = T.let(T.unsafe(nil), Object) + +# Unique value that represents that an `MVar` timed out before it was able +# to produce a value. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mvar.rb#47 +Concurrent::MVar::TIMEOUT = T.let(T.unsafe(nil), Object) + +# `Concurrent::Map` is a hash-like object and should have much better performance +# characteristics, especially under high concurrency, than `Concurrent::Hash`. +# However, `Concurrent::Map `is not strictly semantically equivalent to a ruby `Hash` +# -- for instance, it does not necessarily retain ordering by insertion time as `Hash` +# does. For most uses it should do fine though, and we recommend you consider +# `Concurrent::Map` instead of `Concurrent::Hash` for your concurrency-safe hash needs. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#39 +class Concurrent::Map < ::Concurrent::Collection::MriMapBackend + # Iterates over each key value pair. + # This method is atomic. + # + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + # @return [self] + # @yield for each key value pair in the map + # @yieldparam key [Object] + # @yieldparam value [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#274 + def each; end + + # Iterates over each key. + # This method is atomic. + # + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + # @return [self] + # @yield for each key in the map + # @yieldparam key [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#255 + def each_key; end + + # Iterates over each key value pair. + # This method is atomic. + # + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + # @return [self] + # @yield for each key value pair in the map + # @yieldparam key [Object] + # @yieldparam value [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#274 + def each_pair; end + + # Iterates over each value. + # This method is atomic. + # + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + # @return [self] + # @yield for each value in the map + # @yieldparam value [Object] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#264 + def each_value; end + + # Is map empty? + # + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#291 + def empty?; end + + # Get a value with key, or default_value when key is absent, + # or fail when no default_value is given. + # + # @note The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended + # to be use as a concurrency primitive with strong happens-before + # guarantees. It is not intended to be used as a high-level abstraction + # supporting complex operations. All read and write operations are + # thread safe, but no guarantees are made regarding race conditions + # between the fetch operation and yielding to the block. Additionally, + # this method does not support recursion. This is due to internal + # constraints that are very unlikely to change in the near future. + # @param key [Object] + # @param default_value [Object] + # @raise [KeyError] when key is missing and no default_value is provided + # @return [Object] the value or default value + # @yield default value for a key + # @yieldparam key [Object] + # @yieldreturn [Object] default value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#183 + def fetch(key, default_value = T.unsafe(nil)); end + + # Fetch value with key, or store default value when key is absent, + # or fail when no default_value is given. This is a two step operation, + # therefore not atomic. The store can overwrite other concurrently + # stored value. + # + # @param key [Object] + # @param default_value [Object] + # @return [Object] the value or default value + # @yield default value for a key + # @yieldparam key [Object] + # @yieldreturn [Object] default value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#205 + def fetch_or_store(key, default_value = T.unsafe(nil)); end + + # Get a value with key + # + # @param key [Object] + # @return [Object] the value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb#21 + def get(key); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#321 + def inspect; end + + # Find key of a value. + # + # @param value [Object] + # @return [Object, nil] key or nil when not found + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#284 + def key(value); end + + # All keys + # + # @return [::Array] keys + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#236 + def keys; end + + # @raise [TypeError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#305 + def marshal_dump; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#313 + def marshal_load(hash); end + + # Set a value with key + # + # @param key [Object] + # @param value [Object] + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb#17 + def put(key, value); end + + # Insert value into map with key if key is absent in one atomic step. + # + # @param key [Object] + # @param value [Object] + # @return [Object, nil] the previous value when key was present or nil when there was no key + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#215 + def put_if_absent(key, value); end + + # Is the value stored in the map. Iterates over all values. + # + # @param value [Object] + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#227 + def value?(value); end + + # All values + # + # @return [::Array] values + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#244 + def values; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#331 + def initialize_copy(other); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#336 + def populate_from(hash); end + + # @raise [KeyError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#327 + def raise_fetch_no_key; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/map.rb#341 + def validate_options_hash!(options); end +end + +# Raised when an object with a start/stop lifecycle has been started an +# excessive number of times. Often used in conjunction with a restart +# policy or strategy. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#29 +class Concurrent::MaxRestartFrequencyError < ::Concurrent::Error; end + +# A `Maybe` encapsulates an optional value. A `Maybe` either contains a value +# of (represented as `Just`), or it is empty (represented as `Nothing`). Using +# `Maybe` is a good way to deal with errors or exceptional cases without +# resorting to drastic measures such as exceptions. +# +# `Maybe` is a replacement for the use of `nil` with better type checking. +# +# For compatibility with {Concurrent::Concern::Obligation} the predicate and +# accessor methods are aliased as `fulfilled?`, `rejected?`, `value`, and +# `reason`. +# +# ## Motivation +# +# A common pattern in languages with pattern matching, such as Erlang and +# Haskell, is to return *either* a value *or* an error from a function +# Consider this Erlang code: +# +# ```erlang +# case file:consult("data.dat") of +# {ok, Terms} -> do_something_useful(Terms); +# {error, Reason} -> lager:error(Reason) +# end. +# ``` +# +# In this example the standard library function `file:consult` returns a +# [tuple](http://erlang.org/doc/reference_manual/data_types.html#id69044) +# with two elements: an [atom](http://erlang.org/doc/reference_manual/data_types.html#id64134) +# (similar to a ruby symbol) and a variable containing ancillary data. On +# success it returns the atom `ok` and the data from the file. On failure it +# returns `error` and a string with an explanation of the problem. With this +# pattern there is no ambiguity regarding success or failure. If the file is +# empty the return value cannot be misinterpreted as an error. And when an +# error occurs the return value provides useful information. +# +# In Ruby we tend to return `nil` when an error occurs or else we raise an +# exception. Both of these idioms are problematic. Returning `nil` is +# ambiguous because `nil` may also be a valid value. It also lacks +# information pertaining to the nature of the error. Raising an exception +# is both expensive and usurps the normal flow of control. All of these +# problems can be solved with the use of a `Maybe`. +# +# A `Maybe` is unambiguous with regard to whether or not it contains a value. +# When `Just` it contains a value, when `Nothing` it does not. When `Just` +# the value it contains may be `nil`, which is perfectly valid. When +# `Nothing` the reason for the lack of a value is contained as well. The +# previous Erlang example can be duplicated in Ruby in a principled way by +# having functions return `Maybe` objects: +# +# ```ruby +# result = MyFileUtils.consult("data.dat") # returns a Maybe +# if result.just? +# do_something_useful(result.value) # or result.just +# else +# logger.error(result.reason) # or result.nothing +# end +# ``` +# +# @example Returning a Maybe from a Function +# module MyFileUtils +# def self.consult(path) +# file = File.open(path, 'r') +# Concurrent::Maybe.just(file.read) +# rescue => ex +# return Concurrent::Maybe.nothing(ex) +# ensure +# file.close if file +# end +# end +# +# maybe = MyFileUtils.consult('bogus.file') +# maybe.just? #=> false +# maybe.nothing? #=> true +# maybe.reason #=> # +# +# maybe = MyFileUtils.consult('README.md') +# maybe.just? #=> true +# maybe.nothing? #=> false +# maybe.value #=> "# Concurrent Ruby\n[![Gem Version..." +# @example Using Maybe with a Block +# result = Concurrent::Maybe.from do +# Client.find(10) # Client is an ActiveRecord model +# end +# +# # -- if the record was found +# result.just? #=> true +# result.value #=> # +# +# # -- if the record was not found +# result.just? #=> false +# result.reason #=> ActiveRecord::RecordNotFound +# @example Using Maybe with the Null Object Pattern +# # In a Rails controller... +# result = ClientService.new(10).find # returns a Maybe +# render json: result.or(NullClient.new) +# @see https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html Haskell Data.Maybe +# @see https://github.com/purescript/purescript-maybe/blob/master/docs/Data.Maybe.md PureScript Data.Maybe +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#104 +class Concurrent::Maybe < ::Concurrent::Synchronization::Object + include ::Comparable + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `Maybe` with the given attributes. + # + # @param just [Object] The value when `Just` else `NONE`. + # @param nothing [Exception, Object] The exception when `Nothing` else `NONE`. + # @return [Maybe] The new `Maybe`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#224 + def initialize(just, nothing); end + + # Comparison operator. + # + # @return [Integer] 0 if self and other are both `Nothing`; + # -1 if self is `Nothing` and other is `Just`; + # 1 if self is `Just` and other is nothing; + # `self.just <=> other.just` if both self and other are `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#199 + def <=>(other); end + + # Is this `Maybe` a `Just` (successfully fulfilled with a value)? + # + # @return [Boolean] True if `Just` or false if `Nothing`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#176 + def fulfilled?; end + + # The value of a `Maybe` when `Just`. Will be `NONE` when `Nothing`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#114 + def just; end + + # Is this `Maybe` a `Just` (successfully fulfilled with a value)? + # + # @return [Boolean] True if `Just` or false if `Nothing`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#176 + def just?; end + + # The reason for the `Maybe` when `Nothing`. Will be `NONE` when `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#117 + def nothing; end + + # Is this `Maybe` a `nothing` (rejected with an exception upon fulfillment)? + # + # @return [Boolean] True if `Nothing` or false if `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#184 + def nothing?; end + + # Return either the value of self or the given default value. + # + # @return [Object] The value of self when `Just`; else the given default. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#210 + def or(other); end + + # The reason for the `Maybe` when `Nothing`. Will be `NONE` when `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#117 + def reason; end + + # Is this `Maybe` a `nothing` (rejected with an exception upon fulfillment)? + # + # @return [Boolean] True if `Nothing` or false if `Just`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#184 + def rejected?; end + + # The value of a `Maybe` when `Just`. Will be `NONE` when `Nothing`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#114 + def value; end + + class << self + # Create a new `Maybe` using the given block. + # + # Runs the given block passing all function arguments to the block as block + # arguments. If the block runs to completion without raising an exception + # a new `Just` is created with the value set to the return value of the + # block. If the block raises an exception a new `Nothing` is created with + # the reason being set to the raised exception. + # + # @param args [Array] Zero or more arguments to pass to the block. + # @raise [ArgumentError] when no block given. + # @return [Maybe] The newly created object. + # @yield The block from which to create a new `Maybe`. + # @yieldparam args [Array] Zero or more block arguments passed as + # arguments to the function. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#137 + def from(*args); end + + # Create a new `Just` with the given value. + # + # @param value [Object] The value to set for the new `Maybe` object. + # @return [Maybe] The newly created object. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#152 + def just(value); end + + # Create a new `Nothing` with the given (optional) reason. + # + # @param error [Exception] The reason to set for the new `Maybe` object. + # When given a string a new `StandardError` will be created with the + # argument as the message. When no argument is given a new + # `StandardError` with an empty message will be created. + # @return [Maybe] The newly created object. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#164 + def nothing(error = T.unsafe(nil)); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def new(*args, &block); end + end +end + +# Indicates that the given attribute has not been set. +# When `Just` the {#nothing} getter will return `NONE`. +# When `Nothing` the {#just} getter will return `NONE`. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/maybe.rb#111 +Concurrent::Maybe::NONE = T.let(T.unsafe(nil), Object) + +# Raised when an attempt is made to modify an immutable object +# (such as an `IVar`) after its final state has been set. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#33 +class Concurrent::MultipleAssignmentError < ::Concurrent::Error + # @return [MultipleAssignmentError] a new instance of MultipleAssignmentError + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#36 + def initialize(message = T.unsafe(nil), inspection_data = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#41 + def inspect; end + + # Returns the value of attribute inspection_data. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#34 + def inspection_data; end +end + +# Aggregates multiple exceptions. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#58 +class Concurrent::MultipleErrors < ::Concurrent::Error + # @return [MultipleErrors] a new instance of MultipleErrors + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#61 + def initialize(errors, message = T.unsafe(nil)); end + + # Returns the value of attribute errors. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#59 + def errors; end +end + +# An thread-safe variation of Ruby's standard `Struct`. Values can be set at +# construction or safely changed at any time during the object's lifecycle. +# +# @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#10 +module Concurrent::MutableStruct + include ::Concurrent::Synchronization::AbstractStruct + + # Equality + # + # @return [Boolean] true if other has the same struct subclass and has + # equal member values (according to `Object#==`) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#128 + def ==(other); end + + # Attribute Reference + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the member does not exist + # @raise [IndexError] if the index is out of range. + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#118 + def [](member); end + + # Attribute Assignment + # + # Sets the value of the given struct member or the member at the given index. + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the name does not exist + # @raise [IndexError] if the index is out of range. + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#185 + def []=(member, value); end + + # Yields the value of each struct member in order. If no block is given + # an enumerator is returned. + # + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#139 + def each(&block); end + + # Yields the name and value of each struct member in order. If no block is + # given an enumerator is returned. + # + # @yield the operation to be performed on each struct member/value pair + # @yieldparam member [Object] each struct member (in order) + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#152 + def each_pair(&block); end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#72 + def inspect; end + + # Returns a new struct containing the contents of `other` and the contents + # of `self`. If no block is specified, the value for entries with duplicate + # keys will be that of `other`. Otherwise the value for each duplicate key + # is determined by calling the block with the key, its value in `self` and + # its value in `other`. + # + # @param other [Hash] the hash from which to set the new values + # @raise [ArgumentError] of given a member that is not defined in the struct + # @return [Synchronization::AbstractStruct] a new struct with the new values + # @yield an options block for resolving duplicate keys + # @yieldparam member [String, Symbol] the name of the member which is duplicated + # @yieldparam selfvalue [Object] the value of the member in `self` + # @yieldparam othervalue [Object] the value of the member in `other` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#94 + def merge(other, &block); end + + # Yields each member value from the struct to the block and returns an Array + # containing the member values from the struct for which the given block + # returns a true value (equivalent to `Enumerable#select`). + # + # @return [Array] an array containing each value for which the block returns true + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#167 + def select(&block); end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#51 + def to_a; end + + # Returns a hash containing the names and values for the struct’s members. + # + # @return [Hash] the names and values for the struct’s members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#103 + def to_h; end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#72 + def to_s; end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#51 + def values; end + + # Returns the struct member values for each selector as an Array. + # + # A selector may be either an Integer offset or a Range of offsets (as in `Array#values_at`). + # + # @param indexes [Fixnum, Range] the index(es) from which to obatin the values (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#63 + def values_at(*indexes); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#202 + def initialize_copy(original); end + + class << self + # Factory for creating new struct classes. + # + # ``` + # new([class_name] [, member_name]+>) -> StructClass click to toggle source + # new([class_name] [, member_name]+>) {|StructClass| block } -> StructClass + # new(value, ...) -> obj + # StructClass[value, ...] -> obj + # ``` + # + # The first two forms are used to create a new struct subclass `class_name` + # that can contain a value for each member_name . This subclass can be + # used to create instances of the structure like any other Class . + # + # If the `class_name` is omitted an anonymous struct class will be created. + # Otherwise, the name of this struct will appear as a constant in the struct class, + # so it must be unique for all structs under this base class and must start with a + # capital letter. Assigning a struct class to a constant also gives the class + # the name of the constant. + # + # If a block is given it will be evaluated in the context of `StructClass`, passing + # the created class as a parameter. This is the recommended way to customize a struct. + # Subclassing an anonymous struct creates an extra anonymous class that will never be used. + # + # The last two forms create a new instance of a struct subclass. The number of value + # parameters must be less than or equal to the number of attributes defined for the + # struct. Unset parameters default to nil. Passing more parameters than number of attributes + # will raise an `ArgumentError`. + # + # @see http://ruby-doc.org/core/Struct.html#method-c-new Ruby standard library `Struct#new` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#210 + def new(*args, &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/mutable_struct.rb#220 +Concurrent::MutableStruct::FACTORY = T.let(T.unsafe(nil), T.untyped) + +# A boolean value that can be updated atomically. Reads and writes to an atomic +# boolean and thread-safe and guaranteed to succeed. Reads and writes may block +# briefly but no explicit locking is required. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# Performance: +# +# ``` +# Testing with ruby 2.1.2 +# Testing with Concurrent::MutexAtomicBoolean... +# 2.790000 0.000000 2.790000 ( 2.791454) +# Testing with Concurrent::CAtomicBoolean... +# 0.740000 0.000000 0.740000 ( 0.740206) +# +# Testing with jruby 1.9.3 +# Testing with Concurrent::MutexAtomicBoolean... +# 5.240000 2.520000 7.760000 ( 3.683000) +# Testing with Concurrent::JavaAtomicBoolean... +# 3.340000 0.010000 3.350000 ( 0.855000) +# ``` +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#8 +class Concurrent::MutexAtomicBoolean + extend ::Concurrent::Synchronization::SafeInitialization + + # Creates a new `AtomicBoolean` with the given initial value. + # + # @param initial [Boolean] the initial value + # @return [MutexAtomicBoolean] a new instance of MutexAtomicBoolean + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#12 + def initialize(initial = T.unsafe(nil)); end + + # Is the current value `false` + # + # @return [Boolean] true if the current value is `false`, else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#34 + def false?; end + + # Explicitly sets the value to false. + # + # @return [Boolean] true if value has changed, otherwise false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#44 + def make_false; end + + # Explicitly sets the value to true. + # + # @return [Boolean] true if value has changed, otherwise false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#39 + def make_true; end + + # Is the current value `true` + # + # @return [Boolean] true if the current value is `true`, else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#29 + def true?; end + + # Retrieves the current `Boolean` value. + # + # @return [Boolean] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#19 + def value; end + + # Explicitly sets the value. + # + # @param value [Boolean] the new value to be set + # @return [Boolean] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#24 + def value=(value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#51 + def synchronize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb#62 + def ns_make_value(value); end +end + +# A numeric value that can be updated atomically. Reads and writes to an atomic +# fixnum and thread-safe and guaranteed to succeed. Reads and writes may block +# briefly but no explicit locking is required. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# Performance: +# +# ``` +# Testing with ruby 2.1.2 +# Testing with Concurrent::MutexAtomicFixnum... +# 3.130000 0.000000 3.130000 ( 3.136505) +# Testing with Concurrent::CAtomicFixnum... +# 0.790000 0.000000 0.790000 ( 0.785550) +# +# Testing with jruby 1.9.3 +# Testing with Concurrent::MutexAtomicFixnum... +# 5.460000 2.460000 7.920000 ( 3.715000) +# Testing with Concurrent::JavaAtomicFixnum... +# 4.520000 0.030000 4.550000 ( 1.187000) +# ``` +# +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#9 +class Concurrent::MutexAtomicFixnum + extend ::Concurrent::Synchronization::SafeInitialization + + # Creates a new `AtomicFixnum` with the given initial value. + # + # @param initial [Fixnum] the initial value + # @raise [ArgumentError] if the initial value is not a `Fixnum` + # @return [MutexAtomicFixnum] a new instance of MutexAtomicFixnum + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#13 + def initialize(initial = T.unsafe(nil)); end + + # Atomically sets the value to the given updated value if the current + # value == the expected value. + # + # @param expect [Fixnum] the expected value + # @param update [Fixnum] the new value + # @return [Boolean] true if the value was updated else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#44 + def compare_and_set(expect, update); end + + # Decreases the current value by the given amount (defaults to 1). + # + # @param delta [Fixnum] the amount by which to decrease the current value + # @return [Fixnum] the current value after decrementation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#37 + def decrement(delta = T.unsafe(nil)); end + + # Decreases the current value by the given amount (defaults to 1). + # + # @param delta [Fixnum] the amount by which to decrease the current value + # @return [Fixnum] the current value after decrementation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#37 + def down(delta = T.unsafe(nil)); end + + # Increases the current value by the given amount (defaults to 1). + # + # @param delta [Fixnum] the amount by which to increase the current value + # @return [Fixnum] the current value after incrementation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#30 + def increment(delta = T.unsafe(nil)); end + + # Increases the current value by the given amount (defaults to 1). + # + # @param delta [Fixnum] the amount by which to increase the current value + # @return [Fixnum] the current value after incrementation + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#30 + def up(delta = T.unsafe(nil)); end + + # Pass the current value to the given block, replacing it + # with the block's result. May retry if the value changes + # during the block's execution. + # + # @return [Object] the new value + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam old_value [Object] the starting value of the atomic reference + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#56 + def update; end + + # Retrieves the current `Fixnum` value. + # + # @return [Fixnum] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#20 + def value; end + + # Explicitly sets the value. + # + # @param value [Fixnum] the new value to be set + # @raise [ArgumentError] if the new value is not a `Fixnum` + # @return [Fixnum] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#25 + def value=(value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#65 + def synchronize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb#76 + def ns_set(value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#9 +class Concurrent::MutexAtomicReference + include ::Concurrent::AtomicDirectUpdate + include ::Concurrent::AtomicNumericCompareAndSetWrapper + extend ::Concurrent::Synchronization::SafeInitialization + + # @param value [Object] The initial value. + # @return [MutexAtomicReference] a new instance of MutexAtomicReference + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#16 + def initialize(value = T.unsafe(nil)); end + + # Atomically sets the value to the given updated value if + # the current value == the expected value. + # + # that the actual value was not equal to the expected value. + # + # @param old_value [Object] the expected value + # @param new_value [Object] the new value + # @return [Boolean] `true` if successful. A `false` return indicates + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#45 + def _compare_and_set(old_value, new_value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb#10 + def compare_and_swap(old_value, new_value); end + + # Gets the current value. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#23 + def get; end + + # Atomically sets to the given value and returns the old value. + # + # @param new_value [Object] the new value + # @return [Object] the old value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#35 + def get_and_set(new_value); end + + # Sets to the given value. + # + # @param new_value [Object] the new value + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#29 + def set(new_value); end + + # Atomically sets to the given value and returns the old value. + # + # @param new_value [Object] the new value + # @return [Object] the old value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#35 + def swap(new_value); end + + # Gets the current value. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#23 + def value; end + + # Sets to the given value. + # + # @param new_value [Object] the new value + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#29 + def value=(new_value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb#59 + def synchronize; end +end + +# A synchronization object that allows one thread to wait on multiple other threads. +# The thread that will wait creates a `CountDownLatch` and sets the initial value +# (normally equal to the number of other threads). The initiating thread passes the +# latch to the other threads then waits for the other threads by calling the `#wait` +# method. Each of the other threads calls `#count_down` when done with its work. +# When the latch counter reaches zero the waiting thread is unblocked and continues +# with its work. A `CountDownLatch` can be used only once. Its value cannot be reset. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#9 +class Concurrent::MutexCountDownLatch < ::Concurrent::Synchronization::LockableObject + # Create a new `CountDownLatch` with the initial `count`. + # + # @param count [new] the initial count + # @raise [ArgumentError] if `count` is not an integer or is less than zero + # @return [MutexCountDownLatch] a new instance of MutexCountDownLatch + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#12 + def initialize(count = T.unsafe(nil)); end + + # The current value of the counter. + # + # @return [Fixnum] the current value of the counter + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#34 + def count; end + + # Signal the latch to decrement the counter. Will signal all blocked threads when + # the `count` reaches zero. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#26 + def count_down; end + + # Block on the latch until the counter reaches zero or until `timeout` is reached. + # + # @param timeout [Fixnum] the number of seconds to wait for the counter or `nil` + # to block indefinitely + # @return [Boolean] `true` if the `count` reaches zero else false on `timeout` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#21 + def wait(timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb#40 + def ns_initialize(count); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#9 +class Concurrent::MutexSemaphore < ::Concurrent::Synchronization::LockableObject + # @return [MutexSemaphore] a new instance of MutexSemaphore + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#12 + def initialize(count); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#20 + def acquire(permits = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#38 + def available_permits; end + + # Acquires and returns all permits that are immediately available. + # + # @return [Integer] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#47 + def drain_permits; end + + # Shrinks the number of available permits by the indicated reduction. + # + # @param reduction [Fixnum] Number of permits to remove. + # @raise [ArgumentError] if `reduction` is not an integer or is negative + # @raise [ArgumentError] if `@free` - `@reduction` is less than zero + # @return [nil] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#99 + def reduce_permits(reduction); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#77 + def release(permits = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#54 + def try_acquire(permits = T.unsafe(nil), timeout = T.unsafe(nil)); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#110 + def ns_initialize(count); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#117 + def try_acquire_now(permits); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb#127 + def try_acquire_timed(permits, timeout); end +end + +# Various classes within allows for +nil+ values to be stored, +# so a special +NULL+ token is required to indicate the "nil-ness". +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/constants.rb#6 +Concurrent::NULL = T.let(T.unsafe(nil), Object) + +# Suppresses all output when used for logging. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/concern/logging.rb#103 +Concurrent::NULL_LOGGER = T.let(T.unsafe(nil), Proc) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/options.rb#6 +module Concurrent::Options + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/options.rb#27 + def executor(executor_identifier); end + + # Get the requested `Executor` based on the values set in the options hash. + # + # @option opts + # @param opts [Hash] the options defining the requested executor + # @return [Executor, nil] the requested thread pool, or nil when no option specified + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/options.rb#19 + def executor_from_options(opts = T.unsafe(nil)); end + end +end + +# Promises are inspired by the JavaScript [Promises/A](http://wiki.commonjs.org/wiki/Promises/A) +# and [Promises/A+](http://promises-aplus.github.io/promises-spec/) specifications. +# +# > A promise represents the eventual value returned from the single +# > completion of an operation. +# +# Promises are similar to futures and share many of the same behaviours. +# Promises are far more robust, however. Promises can be chained in a tree +# structure where each promise may have zero or more children. Promises are +# chained using the `then` method. The result of a call to `then` is always +# another promise. Promises are resolved asynchronously (with respect to the +# main thread) but in a strict order: parents are guaranteed to be resolved +# before their children, children before their younger siblings. The `then` +# method takes two parameters: an optional block to be executed upon parent +# resolution and an optional callable to be executed upon parent failure. The +# result of each promise is passed to each of its children upon resolution. +# When a promise is rejected all its children will be summarily rejected and +# will receive the reason. +# +# Promises have several possible states: *:unscheduled*, *:pending*, +# *:processing*, *:rejected*, or *:fulfilled*. These are also aggregated as +# `#incomplete?` and `#complete?`. When a Promise is created it is set to +# *:unscheduled*. Once the `#execute` method is called the state becomes +# *:pending*. Once a job is pulled from the thread pool's queue and is given +# to a thread for processing (often immediately upon `#post`) the state +# becomes *:processing*. The future will remain in this state until processing +# is complete. A future that is in the *:unscheduled*, *:pending*, or +# *:processing* is considered `#incomplete?`. A `#complete?` Promise is either +# *:rejected*, indicating that an exception was thrown during processing, or +# *:fulfilled*, indicating success. If a Promise is *:fulfilled* its `#value` +# will be updated to reflect the result of the operation. If *:rejected* the +# `reason` will be updated with a reference to the thrown exception. The +# predicate methods `#unscheduled?`, `#pending?`, `#rejected?`, and +# `#fulfilled?` can be called at any time to obtain the state of the Promise, +# as can the `#state` method, which returns a symbol. +# +# Retrieving the value of a promise is done through the `value` (alias: +# `deref`) method. Obtaining the value of a promise is a potentially blocking +# operation. When a promise is *rejected* a call to `value` will return `nil` +# immediately. When a promise is *fulfilled* a call to `value` will +# immediately return the current value. When a promise is *pending* a call to +# `value` will block until the promise is either *rejected* or *fulfilled*. A +# *timeout* value can be passed to `value` to limit how long the call will +# block. If `nil` the call will block indefinitely. If `0` the call will not +# block. Any other integer or float value will indicate the maximum number of +# seconds to block. +# +# Promises run on the global thread pool. +# +# ### Examples +# +# Start by requiring promises +# +# ```ruby +# require 'concurrent/promise' +# ``` +# +# Then create one +# +# ```ruby +# p = Concurrent::Promise.execute do +# # do something +# 42 +# end +# ``` +# +# Promises can be chained using the `then` method. The `then` method accepts a +# block and an executor, to be executed on fulfillment, and a callable argument to be executed +# on rejection. The result of the each promise is passed as the block argument +# to chained promises. +# +# ```ruby +# p = Concurrent::Promise.new{10}.then{|x| x * 2}.then{|result| result - 10 }.execute +# ``` +# +# And so on, and so on, and so on... +# +# ```ruby +# p = Concurrent::Promise.fulfill(20). +# then{|result| result - 10 }. +# then{|result| result * 3 }. +# then(executor: different_executor){|result| result % 5 }.execute +# ``` +# +# The initial state of a newly created Promise depends on the state of its parent: +# - if parent is *unscheduled* the child will be *unscheduled* +# - if parent is *pending* the child will be *pending* +# - if parent is *fulfilled* the child will be *pending* +# - if parent is *rejected* the child will be *pending* (but will ultimately be *rejected*) +# +# Promises are executed asynchronously from the main thread. By the time a +# child Promise finishes intialization it may be in a different state than its +# parent (by the time a child is created its parent may have completed +# execution and changed state). Despite being asynchronous, however, the order +# of execution of Promise objects in a chain (or tree) is strictly defined. +# +# There are multiple ways to create and execute a new `Promise`. Both ways +# provide identical behavior: +# +# ```ruby +# # create, operate, then execute +# p1 = Concurrent::Promise.new{ "Hello World!" } +# p1.state #=> :unscheduled +# p1.execute +# +# # create and immediately execute +# p2 = Concurrent::Promise.new{ "Hello World!" }.execute +# +# # execute during creation +# p3 = Concurrent::Promise.execute{ "Hello World!" } +# ``` +# +# Once the `execute` method is called a `Promise` becomes `pending`: +# +# ```ruby +# p = Concurrent::Promise.execute{ "Hello, world!" } +# p.state #=> :pending +# p.pending? #=> true +# ``` +# +# Wait a little bit, and the promise will resolve and provide a value: +# +# ```ruby +# p = Concurrent::Promise.execute{ "Hello, world!" } +# sleep(0.1) +# +# p.state #=> :fulfilled +# p.fulfilled? #=> true +# p.value #=> "Hello, world!" +# ``` +# +# If an exception occurs, the promise will be rejected and will provide +# a reason for the rejection: +# +# ```ruby +# p = Concurrent::Promise.execute{ raise StandardError.new("Here comes the Boom!") } +# sleep(0.1) +# +# p.state #=> :rejected +# p.rejected? #=> true +# p.reason #=> "#" +# ``` +# +# #### Rejection +# +# When a promise is rejected all its children will be rejected and will +# receive the rejection `reason` as the rejection callable parameter: +# +# ```ruby +# p = Concurrent::Promise.execute { Thread.pass; raise StandardError } +# +# c1 = p.then(-> reason { 42 }) +# c2 = p.then(-> reason { raise 'Boom!' }) +# +# c1.wait.state #=> :fulfilled +# c1.value #=> 45 +# c2.wait.state #=> :rejected +# c2.reason #=> # +# ``` +# +# Once a promise is rejected it will continue to accept children that will +# receive immediately rejection (they will be executed asynchronously). +# +# #### Aliases +# +# The `then` method is the most generic alias: it accepts a block to be +# executed upon parent fulfillment and a callable to be executed upon parent +# rejection. At least one of them should be passed. The default block is `{ +# |result| result }` that fulfills the child with the parent value. The +# default callable is `{ |reason| raise reason }` that rejects the child with +# the parent reason. +# +# - `on_success { |result| ... }` is the same as `then {|result| ... }` +# - `rescue { |reason| ... }` is the same as `then(Proc.new { |reason| ... } )` +# - `rescue` is aliased by `catch` and `on_error` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#190 +class Concurrent::Promise < ::Concurrent::IVar + # Initialize a new Promise with the provided options. + # + # @option opts + # @option opts + # @option opts + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Promise] a new instance of Promise + # @see http://wiki.commonjs.org/wiki/Promises/A + # @see http://promises-aplus.github.io/promises-spec/ + # @yield The block operation to be performed asynchronously. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#210 + def initialize(opts = T.unsafe(nil), &block); end + + # Chain onto this promise an action to be undertaken on failure + # (rejection). + # + # @return [Promise] self + # @yield The block to execute + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#360 + def catch(&block); end + + # Execute an `:unscheduled` `Promise`. Immediately sets the state to `:pending` and + # passes the block to a new thread/thread pool for eventual execution. + # Does nothing if the `Promise` is in any state other than `:unscheduled`. + # + # @return [Promise] a reference to `self` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#246 + def execute; end + + # Set the `IVar` to failed due to some error and wake or notify all threads waiting on it. + # + # @param reason [Object] for the failure + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @raise [Concurrent::PromiseExecutionError] if not the root promise + # @return [IVar] self + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#278 + def fail(reason = T.unsafe(nil)); end + + # Yield the successful result to the block that returns a promise. If that + # promise is also successful the result is the result of the yielded promise. + # If either part fails the whole also fails. + # + # @example + # Promise.execute { 1 }.flat_map { |v| Promise.execute { v + 2 } }.value! #=> 3 + # @return [Promise] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#375 + def flat_map(&block); end + + # Chain onto this promise an action to be undertaken on failure + # (rejection). + # + # @return [Promise] self + # @yield The block to execute + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#360 + def on_error(&block); end + + # Chain onto this promise an action to be undertaken on success + # (fulfillment). + # + # @raise [ArgumentError] + # @return [Promise] self + # @yield The block to execute + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#349 + def on_success(&block); end + + # Chain onto this promise an action to be undertaken on failure + # (rejection). + # + # @return [Promise] self + # @yield The block to execute + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#360 + def rescue(&block); end + + # Set the `IVar` to a value and wake or notify all threads waiting on it. + # + # @param value [Object] the value to store in the `IVar` + # @raise [ArgumentError] if both a value and a block are given + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @raise [Concurrent::PromiseExecutionError] if not the root promise + # @return [IVar] self + # @yield A block operation to use for setting the value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#262 + def set(value = T.unsafe(nil), &block); end + + # Chain a new promise off the current promise. + # + # @overload then + # @overload then + # @raise [ArgumentError] + # @return [Promise] the new promise + # @yield The block operation to be performed asynchronously. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#314 + def then(*args, &block); end + + # Builds a promise that produces the result of self and others in an Array + # and fails if any of them fails. + # + # @overload zip + # @overload zip + # @return [Promise] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#440 + def zip(*others); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#551 + def complete(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#545 + def notify_child(child); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#481 + def ns_initialize(value, opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#533 + def on_fulfill(result); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#539 + def on_reject(reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#562 + def realize(task); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#528 + def root?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#520 + def set_pending; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#570 + def set_state!(success, value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#576 + def synchronized_set_state!(success, value, reason); end + + class << self + # Aggregate a collection of zero or more promises under a composite promise, + # execute the aggregated promises and collect them into a standard Ruby array, + # call the given Ruby `Ennnumerable` predicate (such as `any?`, `all?`, `none?`, + # or `one?`) on the collection checking for the success or failure of each, + # then executing the composite's `#then` handlers if the predicate returns + # `true` or executing the composite's `#rescue` handlers if the predicate + # returns false. + # + # + # The returned promise will not yet have been executed. Additional `#then` + # and `#rescue` handlers may still be provided. Once the returned promise + # is execute the aggregate promises will be also be executed (if they have + # not been executed already). The results of the aggregate promises will + # be checked upon completion. The necessary `#then` and `#rescue` blocks + # on the aggregating promise will then be executed as appropriate. If the + # `#rescue` handlers are executed the raises exception will be + # `Concurrent::PromiseExecutionError`. + # + # @param promises [Array] Zero or more promises to aggregate + # @return [Promise] an unscheduled (not executed) promise that aggregates + # the promises given as arguments + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#505 + def aggregate(method, *promises); end + + # Aggregates a collection of promises and executes the `then` condition + # if all aggregated promises succeed. Executes the `rescue` handler with + # a `Concurrent::PromiseExecutionError` if any of the aggregated promises + # fail. Upon execution will execute any of the aggregate promises that + # were not already executed. + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#464 + def all?(*promises); end + + # Aggregates a collection of promises and executes the `then` condition + # if any aggregated promises succeed. Executes the `rescue` handler with + # a `Concurrent::PromiseExecutionError` if any of the aggregated promises + # fail. Upon execution will execute any of the aggregate promises that + # were not already executed. + # + # + # The returned promise will not yet have been executed. Additional `#then` + # and `#rescue` handlers may still be provided. Once the returned promise + # is execute the aggregate promises will be also be executed (if they have + # not been executed already). The results of the aggregate promises will + # be checked upon completion. The necessary `#then` and `#rescue` blocks + # on the aggregating promise will then be executed as appropriate. If the + # `#rescue` handlers are executed the raises exception will be + # `Concurrent::PromiseExecutionError`. + # + # @param promises [Array] Zero or more promises to aggregate + # @return [Promise] an unscheduled (not executed) promise that aggregates + # the promises given as arguments + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#475 + def any?(*promises); end + + # Create a new `Promise` object with the given block, execute it, and return the + # `:pending` object. + # + # @example + # promise = Concurrent::Promise.execute{ sleep(1); 42 } + # promise.state #=> :pending + # @option opts + # @option opts + # @option opts + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Promise] the newly created `Promise` in the `:pending` state + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#296 + def execute(opts = T.unsafe(nil), &block); end + + # Create a new `Promise` and fulfill it immediately. + # + # @option opts + # @option opts + # @option opts + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Promise] the newly created `Promise` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#224 + def fulfill(value, opts = T.unsafe(nil)); end + + # Create a new `Promise` and reject it immediately. + # + # @option opts + # @option opts + # @option opts + # @option opts + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] if no block is given + # @return [Promise] the newly created `Promise` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#237 + def reject(reason, opts = T.unsafe(nil)); end + + # Builds a promise that produces the result of promises in an Array + # and fails if any of them fails. + # + # @overload zip + # @overload zip + # @return [Promise] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#409 + def zip(*promises); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promise.rb#11 +class Concurrent::PromiseExecutionError < ::StandardError; end + +# {include:file:docs-source/promises-main.md} +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#13 +module Concurrent::Promises + extend ::Concurrent::Promises::FactoryMethods::Configuration + extend ::Concurrent::Promises::FactoryMethods +end + +# @abstract +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2047 +class Concurrent::Promises::AbstractAnyPromise < ::Concurrent::Promises::BlockedPromise; end + +# Common ancestor of {Event} and {Future} classes, many shared methods are defined here. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#513 +class Concurrent::Promises::AbstractEventFuture < ::Concurrent::Synchronization::Object + include ::Concurrent::Promises::InternalStates + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [AbstractEventFuture] a new instance of AbstractEventFuture + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#522 + def initialize(promise, default_executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#738 + def add_callback_clear_delayed_node(node); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#733 + def add_callback_notify_blocked(promise, index); end + + # For inspection. + # + # @return [Array] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#702 + def blocks; end + + # For inspection. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#710 + def callbacks; end + + # Shortcut of {#chain_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #chain_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#596 + def chain(*args, &task); end + + # Chains the task to be executed asynchronously on executor after it is resolved. + # + # @overload an_event.chain_on + # @overload a_future.chain_on + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [Future] + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#614 + def chain_on(executor, *args, &task); end + + # Resolves the resolvable when receiver is resolved. + # + # @param resolvable [Resolvable] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#629 + def chain_resolvable(resolvable); end + + # Returns default executor. + # + # @return [Executor] default executor + # @see #with_default_executor + # @see FactoryMethods#future_on + # @see FactoryMethods#resolvable_future + # @see FactoryMethods#any_fulfilled_future_on + # @see similar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#590 + def default_executor; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#619 + def inspect; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def internal_state; end + + # Shortcut of {#on_resolution_using} with default `:io` executor supplied. + # + # @return [self] + # @see #on_resolution_using + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#637 + def on_resolution(*args, &callback); end + + # Stores the callback to be executed synchronously on resolving thread after it is + # resolved. + # + # @overload an_event.on_resolution! + # @overload a_future.on_resolution! + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#655 + def on_resolution!(*args, &callback); end + + # Stores the callback to be executed asynchronously on executor after it is resolved. + # + # @overload an_event.on_resolution_using + # @overload a_future.on_resolution_using + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#673 + def on_resolution_using(executor, *args, &callback); end + + # Is it in pending state? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#549 + def pending?; end + + # For inspection. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#716 + def promise; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#688 + def resolve_with(state, raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Is it in resolved state? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#555 + def resolved?; end + + # Returns its state. + # + # @overload an_event.state + # @overload a_future.state + # @return [Symbol] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#543 + def state; end + + # Resolves the resolvable when receiver is resolved. + # + # @param resolvable [Resolvable] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#629 + def tangle(resolvable); end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#619 + def to_s; end + + # Propagates touch. Requests all the delayed futures, which it depends on, to be + # executed. This method is called by any other method requiring resolved state, like {#wait}. + # + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#562 + def touch; end + + # For inspection. + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#722 + def touched?; end + + # Wait (block the Thread) until receiver is {#resolved?}. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @param timeout [Numeric] the maximum time in second to wait. + # @return [self, true, false] self implies timeout was not used, true implies timeout was used + # and it was resolved, false implies it was not resolved within timeout. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#578 + def wait(timeout = T.unsafe(nil)); end + + # For inspection. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#728 + def waiting_threads; end + + # Crates new object with same class with the executor set as its new default executor. + # Any futures depending on it will use the new default executor. + # + # @abstract + # @raise [NotImplementedError] + # @return [AbstractEventFuture] + # @see Event#with_default_executor + # @see Future#with_default_executor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#683 + def with_default_executor(executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#743 + def with_hidden_resolvable; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#750 + def add_callback(method, *args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#812 + def async_callback_on_resolution(state, executor, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#796 + def call_callback(method, state, args); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#800 + def call_callbacks(state); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#763 + def callback_clear_delayed_node(state, node); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#818 + def callback_notify_blocked(state, promise, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_internal_state(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def internal_state=(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_internal_state(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_internal_state(&block); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#768 + def wait_until_resolved(timeout); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#808 + def with_async(executor, *args, &block); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1796 +class Concurrent::Promises::AbstractFlatPromise < ::Concurrent::Promises::BlockedPromise + # @return [AbstractFlatPromise] a new instance of AbstractFlatPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1798 + def initialize(delayed_because, blockers_count, event_or_future); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1808 + def touch; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1828 + def add_delayed_of(future); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1820 + def on_resolvable(resolved_future, index); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1824 + def resolvable?(countdown, future, index); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1816 + def touched?; end +end + +# @abstract +# @private +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1549 +class Concurrent::Promises::AbstractPromise < ::Concurrent::Synchronization::Object + include ::Concurrent::Promises::InternalStates + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [AbstractPromise] a new instance of AbstractPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1553 + def initialize(future); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1564 + def default_executor; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1581 + def delayed_because; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1558 + def event; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1558 + def future; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1575 + def inspect; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1568 + def state; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1575 + def to_s; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1572 + def touch; end + + private + + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1592 + def evaluate_to(*args, block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1587 + def resolve_with(new_state, raise_on_reassign = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2084 +class Concurrent::Promises::AnyFulfilledFuturePromise < ::Concurrent::Promises::AnyResolvedFuturePromise + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2088 + def resolvable?(countdown, event_or_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2050 +class Concurrent::Promises::AnyResolvedEventPromise < ::Concurrent::Promises::AbstractAnyPromise + # @return [AnyResolvedEventPromise] a new instance of AnyResolvedEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2054 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2062 + def on_resolvable(resolved_future, index); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2058 + def resolvable?(countdown, future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2067 +class Concurrent::Promises::AnyResolvedFuturePromise < ::Concurrent::Promises::AbstractAnyPromise + # @return [AnyResolvedFuturePromise] a new instance of AnyResolvedFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2071 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2079 + def on_resolvable(resolved_future, index); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2075 + def resolvable?(countdown, future, index); end +end + +# @abstract +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1619 +class Concurrent::Promises::BlockedPromise < ::Concurrent::Promises::InnerPromise + # @return [BlockedPromise] a new instance of BlockedPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1661 + def initialize(delayed, blockers_count, future); end + + # for inspection only + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1683 + def blocked_by; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1674 + def delayed_because; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1667 + def on_blocker_resolution(future, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1678 + def touch; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1691 + def clear_and_propagate_touch(stack_or_element = T.unsafe(nil)); end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1710 + def on_resolvable(resolved_future, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1706 + def process_on_blocker_resolution(future, index); end + + # @return [true, false] if resolvable + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1702 + def resolvable?(countdown, future, index); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1652 + def add_delayed(delayed1, delayed2); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1645 + def new_blocked_by(blockers, *args, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1623 + def new_blocked_by1(blocker, *args, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1630 + def new_blocked_by2(blocker1, blocker2, *args, &block); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def new(*args, &block); end + end +end + +# @abstract +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1716 +class Concurrent::Promises::BlockedTaskPromise < ::Concurrent::Promises::BlockedPromise + # @raise [ArgumentError] + # @return [BlockedTaskPromise] a new instance of BlockedTaskPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1717 + def initialize(delayed, blockers_count, default_executor, executor, args, &task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1725 + def executor; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1766 +class Concurrent::Promises::ChainPromise < ::Concurrent::Promises::BlockedTaskPromise + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1769 + def on_resolvable(resolved_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2095 +class Concurrent::Promises::DelayPromise < ::Concurrent::Promises::InnerPromise + # @return [DelayPromise] a new instance of DelayPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2097 + def initialize(default_executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2108 + def delayed_because; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2104 + def touch; end +end + +# Represents an event which will happen in future (will be resolved). The event is either +# pending or resolved. It should be always resolved. Use {Future} to communicate rejections and +# cancellation. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#826 +class Concurrent::Promises::Event < ::Concurrent::Promises::AbstractEventFuture + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future, Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#839 + def &(other); end + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#853 + def any(event_or_future); end + + # Creates new event dependent on receiver which will not evaluate until touched, see {#touch}. + # In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#863 + def delay; end + + # Creates new event dependent on receiver scheduled to execute on/in intended_time. + # In time is interpreted from the moment the receiver is resolved, therefore it inserts + # delay into the chain. + # + # @param intended_time [Numeric, Time] `Numeric` means to run in `intended_time` seconds. + # `Time` means to run on `intended_time`. + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#875 + def schedule(intended_time); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#596 + def then(*args, &task); end + + # Returns self, since this is event + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#893 + def to_event; end + + # Converts event to a future. The future is fulfilled when the event is resolved, the future may never fail. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#885 + def to_future; end + + # Crates new object with same class with the executor set as its new default executor. + # Any futures depending on it will use the new default executor. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#899 + def with_default_executor(executor); end + + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future, Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#839 + def zip(other); end + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#853 + def |(event_or_future); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#910 + def callback_on_resolution(state, args, callback); end + + # @raise [Concurrent::MultipleAssignmentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#905 + def rejected_resolution(raise_on_reassign, state); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1972 +class Concurrent::Promises::EventWrapperPromise < ::Concurrent::Promises::BlockedPromise + # @return [EventWrapperPromise] a new instance of EventWrapperPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1973 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1979 + def on_resolvable(resolved_future, index); end +end + +# Container of all {Future}, {Event} factory methods. They are never constructed directly with +# new. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#46 +module Concurrent::Promises::FactoryMethods + include ::Concurrent::Promises::FactoryMethods::Configuration + extend ::Concurrent::ReInclude + extend ::Concurrent::Promises::FactoryMethods::Configuration + extend ::Concurrent::Promises::FactoryMethods + + # Shortcut of {#any_resolved_future_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #any_resolved_future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#278 + def any(*futures_and_or_events); end + + # Shortcut of {#any_event_on} with default `:io` executor supplied. + # + # @return [Event] + # @see #any_event_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#319 + def any_event(*futures_and_or_events); end + + # Creates a new event which becomes resolved after the first futures_and_or_events resolves. + # If resolved it does not propagate {Concurrent::AbstractEventFuture#touch}, leaving delayed + # futures un-executed if they are not required any more. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#329 + def any_event_on(default_executor, *futures_and_or_events); end + + # Shortcut of {#any_fulfilled_future_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #any_fulfilled_future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#300 + def any_fulfilled_future(*futures_and_or_events); end + + # Creates a new future which is resolved after the first futures_and_or_events is fulfilled. + # Its result equals the result of the first resolved future or if all futures_and_or_events reject, + # it has reason of the last rejected future. + # If resolved it does not propagate {Concurrent::AbstractEventFuture#touch}, leaving delayed + # futures un-executed if they are not required any more. + # If event is supplied, which does not have value and can be only resolved, it's + # represented as `:fulfilled` with value `nil`. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#313 + def any_fulfilled_future_on(default_executor, *futures_and_or_events); end + + # Shortcut of {#any_resolved_future_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #any_resolved_future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#278 + def any_resolved_future(*futures_and_or_events); end + + # Creates a new future which is resolved after the first futures_and_or_events is resolved. + # Its result equals the result of the first resolved future. + # If resolved it does not propagate {Concurrent::AbstractEventFuture#touch}, leaving delayed + # futures un-executed if they are not required any more. + # If event is supplied, which does not have value and can be only resolved, it's + # represented as `:fulfilled` with value `nil`. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#294 + def any_resolved_future_on(default_executor, *futures_and_or_events); end + + # Shortcut of {#delay_on} with default `:io` executor supplied. + # + # @return [Future, Event] + # @see #delay_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#190 + def delay(*args, &task); end + + # Creates a new event or future which is resolved only after it is touched, + # see {Concurrent::AbstractEventFuture#touch}. + # + # @overload delay_on + # @overload delay_on + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#207 + def delay_on(default_executor, *args, &task); end + + # Creates a resolved future which will be fulfilled with the given value. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param value [Object] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#127 + def fulfilled_future(value, default_executor = T.unsafe(nil)); end + + # Shortcut of {#future_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#94 + def future(*args, &task); end + + # Constructs a new Future which will be resolved after block is evaluated on default executor. + # Evaluation begins immediately. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [Future] + # @yield [*args] to the task. + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#106 + def future_on(default_executor, *args, &task); end + + # General constructor. Behaves differently based on the argument's type. It's provided for convenience + # but it's better to be explicit. + # + # @overload make_future + # @overload make_future + # @overload make_future + # @overload make_future + # @overload make_future + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [Event, Future] + # @see rejected_future, resolved_event, fulfilled_future + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#174 + def make_future(argument = T.unsafe(nil), default_executor = T.unsafe(nil)); end + + # Creates a resolved future which will be rejected with the given reason. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param reason [Object] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#136 + def rejected_future(reason, default_executor = T.unsafe(nil)); end + + # Shortcut of {#resolvable_event_on} with default `:io` executor supplied. + # + # @return [ResolvableEvent] + # @see #resolvable_event_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#63 + def resolvable_event; end + + # Creates a resolvable event, user is responsible for resolving the event once + # by calling {Promises::ResolvableEvent#resolve}. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [ResolvableEvent] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#72 + def resolvable_event_on(default_executor = T.unsafe(nil)); end + + # Shortcut of {#resolvable_future_on} with default `:io` executor supplied. + # + # @return [ResolvableFuture] + # @see #resolvable_future_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#78 + def resolvable_future; end + + # Creates resolvable future, user is responsible for resolving the future once by + # {Promises::ResolvableFuture#resolve}, {Promises::ResolvableFuture#fulfill}, + # or {Promises::ResolvableFuture#reject} + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [ResolvableFuture] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#88 + def resolvable_future_on(default_executor = T.unsafe(nil)); end + + # Creates resolved event. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#144 + def resolved_event(default_executor = T.unsafe(nil)); end + + # Creates a resolved future with will be either fulfilled with the given value or rejected with + # the given reason. + # + # @param fulfilled [true, false] + # @param value [Object] + # @param reason [Object] + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#118 + def resolved_future(fulfilled, value, reason, default_executor = T.unsafe(nil)); end + + # Shortcut of {#schedule_on} with default `:io` executor supplied. + # + # @return [Future, Event] + # @see #schedule_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#214 + def schedule(intended_time, *args, &task); end + + # Creates a new event or future which is resolved in intended_time. + # + # @overload schedule_on + # @overload schedule_on + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param intended_time [Numeric, Time] `Numeric` means to run in `intended_time` seconds. + # `Time` means to run on `intended_time`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#233 + def schedule_on(default_executor, intended_time, *args, &task); end + + # Shortcut of {#zip_futures_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #zip_futures_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#240 + def zip(*futures_and_or_events); end + + # Shortcut of {#zip_events_on} with default `:io` executor supplied. + # + # @return [Event] + # @see #zip_events_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#262 + def zip_events(*futures_and_or_events); end + + # Creates a new event which is resolved after all futures_and_or_events are resolved. + # (Future is resolved when fulfilled or rejected.) + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#272 + def zip_events_on(default_executor, *futures_and_or_events); end + + # Shortcut of {#zip_futures_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #zip_futures_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#240 + def zip_futures(*futures_and_or_events); end + + # Creates a new future which is resolved after all futures_and_or_events are resolved. + # Its value is an array of zipped future values. Its reason is an array of reasons for rejection. + # If there is an error it rejects. + # If event is supplied, which does not have value and can be only resolved, it's + # represented as `:fulfilled` with value `nil`. + # + # @param default_executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # @param futures_and_or_events [AbstractEventFuture] + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#254 + def zip_futures_on(default_executor, *futures_and_or_events); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#50 +module Concurrent::Promises::FactoryMethods::Configuration + # @return [Executor, :io, :fast] the executor which is used when none is supplied + # to a factory method. The method can be overridden in the receivers of + # `include FactoryMethod` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#54 + def default_executor; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1840 +class Concurrent::Promises::FlatEventPromise < ::Concurrent::Promises::AbstractFlatPromise + # @return [FlatEventPromise] a new instance of FlatEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1844 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1848 + def process_on_blocker_resolution(future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1873 +class Concurrent::Promises::FlatFuturePromise < ::Concurrent::Promises::AbstractFlatPromise + # @raise [ArgumentError] + # @return [FlatFuturePromise] a new instance of FlatFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1877 + def initialize(delayed, blockers_count, levels, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1884 + def process_on_blocker_resolution(future, index); end +end + +# Represents a value which will become available in future. May reject with a reason instead, +# e.g. when the tasks raises an exception. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#917 +class Concurrent::Promises::Future < ::Concurrent::Promises::AbstractEventFuture + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1070 + def &(other); end + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. Returning future will have value nil if event_or_future is event and resolves + # first. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1085 + def any(event_or_future); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1215 + def apply(args, block); end + + # Creates new future dependent on receiver which will not evaluate until touched, see {#touch}. + # In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1095 + def delay; end + + # Allows rejected Future to be risen with `raise` method. + # If the reason is not an exception `Runtime.new(reason)` is returned. + # + # @example + # raise Promises.rejected_future(StandardError.new("boom")) + # raise Promises.rejected_future("or just boom") + # @raise [Concurrent::Error] when raising not rejected future + # @return [Exception] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1013 + def exception(*args); end + + # Creates new future which will have result of the future returned by receiver. If receiver + # rejects it will have its rejection. + # + # @param level [Integer] how many levels of futures should flatten + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1120 + def flat(level = T.unsafe(nil)); end + + # Creates new event which will be resolved when the returned event by receiver is. + # Be careful if the receiver rejects it will just resolve since Event does not hold reason. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1130 + def flat_event; end + + # Creates new future which will have result of the future returned by receiver. If receiver + # rejects it will have its rejection. + # + # @param level [Integer] how many levels of futures should flatten + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1120 + def flat_future(level = T.unsafe(nil)); end + + # Is it in fulfilled state? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#921 + def fulfilled?; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1235 + def inspect; end + + # Shortcut of {#on_fulfillment_using} with default `:io` executor supplied. + # + # @return [self] + # @see #on_fulfillment_using + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1136 + def on_fulfillment(*args, &callback); end + + # Stores the callback to be executed synchronously on resolving thread after it is + # fulfilled. Does nothing on rejection. + # + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yield [value, *args] to the callback. + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1147 + def on_fulfillment!(*args, &callback); end + + # Stores the callback to be executed asynchronously on executor after it is + # fulfilled. Does nothing on rejection. + # + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yield [value, *args] to the callback. + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1159 + def on_fulfillment_using(executor, *args, &callback); end + + # Shortcut of {#on_rejection_using} with default `:io` executor supplied. + # + # @return [self] + # @see #on_rejection_using + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1165 + def on_rejection(*args, &callback); end + + # Stores the callback to be executed synchronously on resolving thread after it is + # rejected. Does nothing on fulfillment. + # + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yield [reason, *args] to the callback. + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1176 + def on_rejection!(*args, &callback); end + + # Stores the callback to be executed asynchronously on executor after it is + # rejected. Does nothing on fulfillment. + # + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [self] + # @yield [reason, *args] to the callback. + # @yieldreturn is forgotten. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1188 + def on_rejection_using(executor, *args, &callback); end + + # Returns reason of future's rejection. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @note Make sure returned `nil` is not confused with timeout, no value when rejected, + # no reason when fulfilled, etc. + # Use more exact methods if needed, like {#wait}, {#value!}, {#result}, etc. + # @param timeout [Numeric] the maximum time in second to wait. + # @param timeout_value [Object] a value returned by the method when it times out + # @return [Object, timeout_value] the reason, or timeout_value on timeout, or nil on fulfillment. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#966 + def reason(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil)); end + + # Is it in rejected state? + # + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#928 + def rejected?; end + + # Shortcut of {#rescue_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #rescue_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1052 + def rescue(*args, &task); end + + # Chains the task to be executed asynchronously on executor after it rejects. Does not run + # the task if it fulfills. It will resolve though, triggering any dependent futures. + # + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [Future] + # @yield [reason, *args] to the task. + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1064 + def rescue_on(executor, *args, &task); end + + # Returns triplet fulfilled?, value, reason. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @param timeout [Numeric] the maximum time in second to wait. + # @return [Array(Boolean, Object, Object), nil] triplet of fulfilled?, value, reason, or nil + # on timeout. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#981 + def result(timeout = T.unsafe(nil)); end + + # Allows to use futures as green threads. The receiver has to evaluate to a future which + # represents what should be done next. It basically flattens indefinitely until non Future + # values is returned which becomes result of the returned future. Any encountered exception + # will become reason of the returned future. + # + # @example + # body = lambda do |v| + # v += 1 + # v < 5 ? Promises.future(v, &body) : v + # end + # Promises.future(0, &body).run.value! # => 5 + # @param run_test [#call(value)] an object which when called returns either Future to keep running with + # or nil, then the run completes with the value. + # The run_test can be used to extract the Future from deeper structure, + # or to distinguish Future which is a resulting value from a future + # which is suppose to continue running. + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1210 + def run(run_test = T.unsafe(nil)); end + + # Creates new event dependent on receiver scheduled to execute on/in intended_time. + # In time is interpreted from the moment the receiver is resolved, therefore it inserts + # delay into the chain. + # + # @param intended_time [Numeric, Time] `Numeric` means to run in `intended_time` seconds. + # `Time` means to run on `intended_time`. + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1102 + def schedule(intended_time); end + + # Shortcut of {#then_on} with default `:io` executor supplied. + # + # @return [Future] + # @see #then_on + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1034 + def then(*args, &task); end + + # Chains the task to be executed asynchronously on executor after it fulfills. Does not run + # the task if it rejects. It will resolve though, triggering any dependent futures. + # + # @param executor [Executor, :io, :fast] Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # @param args [Object] arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # @return [Future] + # @yield [value, *args] to the task. + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1046 + def then_on(executor, *args, &task); end + + # Converts future to event which is resolved when future is resolved by fulfillment or rejection. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1222 + def to_event; end + + # Returns self, since this is a future + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1230 + def to_future; end + + # @return [String] Short string representation. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1235 + def to_s; end + + # Return value of the future. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @note Make sure returned `nil` is not confused with timeout, no value when rejected, + # no reason when fulfilled, etc. + # Use more exact methods if needed, like {#wait}, {#value!}, {#result}, etc. + # @param timeout [Numeric] the maximum time in second to wait. + # @param timeout_value [Object] a value returned by the method when it times out + # @return [Object, nil, timeout_value] the value of the Future when fulfilled, + # timeout_value on timeout, + # nil on rejection. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#950 + def value(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil)); end + + # Return value of the future. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @note Make sure returned `nil` is not confused with timeout, no value when rejected, + # no reason when fulfilled, etc. + # Use more exact methods if needed, like {#wait}, {#value!}, {#result}, etc. + # @param timeout [Numeric] the maximum time in second to wait. + # @param timeout_value [Object] a value returned by the method when it times out + # @raise [Exception] {#reason} on rejection + # @return [Object, nil, timeout_value] the value of the Future when fulfilled, + # or nil on rejection, + # or timeout_value on timeout. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#997 + def value!(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil)); end + + # Wait (block the Thread) until receiver is {#resolved?}. + # Calls {Concurrent::AbstractEventFuture#touch}. + # + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + # @param timeout [Numeric] the maximum time in second to wait. + # @raise [Exception] {#reason} on rejection + # @return [self, true, false] self implies timeout was not used, true implies timeout was used + # and it was resolved, false implies it was not resolved within timeout. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#987 + def wait!(timeout = T.unsafe(nil)); end + + # Crates new object with same class with the executor set as its new default executor. + # Any futures depending on it will use the new default executor. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1111 + def with_default_executor(executor); end + + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1070 + def zip(other); end + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. Returning future will have value nil if event_or_future is event and resolves + # first. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1085 + def |(event_or_future); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1272 + def async_callback_on_fulfillment(state, executor, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1278 + def async_callback_on_rejection(state, executor, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1284 + def callback_on_fulfillment(state, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1288 + def callback_on_rejection(state, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1292 + def callback_on_resolution(state, args, callback); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1251 + def rejected_resolution(raise_on_reassign, state); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1247 + def run_test(v); end + + # @raise [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1266 + def wait_until_resolved!(timeout = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1984 +class Concurrent::Promises::FutureWrapperPromise < ::Concurrent::Promises::BlockedPromise + # @return [FutureWrapperPromise] a new instance of FutureWrapperPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1985 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1991 + def on_resolvable(resolved_future, index); end +end + +# will be immediately resolved +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1783 +class Concurrent::Promises::ImmediateEventPromise < ::Concurrent::Promises::InnerPromise + # @return [ImmediateEventPromise] a new instance of ImmediateEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1784 + def initialize(default_executor); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1789 +class Concurrent::Promises::ImmediateFuturePromise < ::Concurrent::Promises::InnerPromise + # @return [ImmediateFuturePromise] a new instance of ImmediateFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1790 + def initialize(default_executor, fulfilled, value, reason); end +end + +# @abstract +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1615 +class Concurrent::Promises::InnerPromise < ::Concurrent::Promises::AbstractPromise; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#338 +module Concurrent::Promises::InternalStates; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#397 +class Concurrent::Promises::InternalStates::Fulfilled < ::Concurrent::Promises::InternalStates::ResolvedWithResult + # @return [Fulfilled] a new instance of Fulfilled + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#399 + def initialize(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#407 + def apply(args, block); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#403 + def fulfilled?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#415 + def reason; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#419 + def to_sym; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#411 + def value; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#425 +class Concurrent::Promises::InternalStates::FulfilledArray < ::Concurrent::Promises::InternalStates::Fulfilled + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#426 + def apply(args, block); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#488 +Concurrent::Promises::InternalStates::PENDING = T.let(T.unsafe(nil), Concurrent::Promises::InternalStates::Pending) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#459 +class Concurrent::Promises::InternalStates::PartiallyRejected < ::Concurrent::Promises::InternalStates::ResolvedWithResult + # @return [PartiallyRejected] a new instance of PartiallyRejected + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#460 + def initialize(value, reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#482 + def apply(args, block); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#466 + def fulfilled?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#478 + def reason; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#470 + def to_sym; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#474 + def value; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#351 +class Concurrent::Promises::InternalStates::Pending < ::Concurrent::Promises::InternalStates::State + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#352 + def resolved?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#356 + def to_sym; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#490 +Concurrent::Promises::InternalStates::RESERVED = T.let(T.unsafe(nil), Concurrent::Promises::InternalStates::Reserved) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#492 +Concurrent::Promises::InternalStates::RESOLVED = T.let(T.unsafe(nil), Concurrent::Promises::InternalStates::Fulfilled) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#432 +class Concurrent::Promises::InternalStates::Rejected < ::Concurrent::Promises::InternalStates::ResolvedWithResult + # @return [Rejected] a new instance of Rejected + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#433 + def initialize(reason); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#453 + def apply(args, block); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#437 + def fulfilled?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#445 + def reason; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#449 + def to_sym; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#441 + def value; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#362 +class Concurrent::Promises::InternalStates::Reserved < ::Concurrent::Promises::InternalStates::Pending; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#366 +class Concurrent::Promises::InternalStates::ResolvedWithResult < ::Concurrent::Promises::InternalStates::State + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#391 + def apply; end + + # @raise [NotImplementedError] + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#379 + def fulfilled?; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#387 + def reason; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#367 + def resolved?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#375 + def result; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#371 + def to_sym; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#383 + def value; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#340 +class Concurrent::Promises::InternalStates::State + # @raise [NotImplementedError] + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#341 + def resolved?; end + + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#345 + def to_sym; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1748 +class Concurrent::Promises::RescuePromise < ::Concurrent::Promises::BlockedTaskPromise + # @return [RescuePromise] a new instance of RescuePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1751 + def initialize(delayed, blockers_count, default_executor, executor, args, &task); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1755 + def on_resolvable(resolved_future, index); end +end + +# Marker module of Future, Event resolved manually. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1299 +module Concurrent::Promises::Resolvable + include ::Concurrent::Promises::InternalStates +end + +# A Event which can be resolved by user. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1304 +class Concurrent::Promises::ResolvableEvent < ::Concurrent::Promises::Event + include ::Concurrent::Promises::Resolvable + + # Makes the event resolved, which triggers all dependent futures. + # + # @param raise_on_reassign [Boolean] should method raise exception if already resolved + # @param reserved [true, false] Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1324 + def resolve(raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Behaves as {AbstractEventFuture#wait} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [true, false] If it times out and the argument is true it will also resolve the event. + # @return [self, true, false] + # @see AbstractEventFuture#wait + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1342 + def wait(timeout = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Creates new event wrapping receiver, effectively hiding the resolve method. + # + # @return [Event] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1331 + def with_hidden_resolvable; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1600 +class Concurrent::Promises::ResolvableEventPromise < ::Concurrent::Promises::AbstractPromise + # @return [ResolvableEventPromise] a new instance of ResolvableEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1601 + def initialize(default_executor); end +end + +# A Future which can be resolved by user. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1354 +class Concurrent::Promises::ResolvableFuture < ::Concurrent::Promises::Future + include ::Concurrent::Promises::Resolvable + + # Evaluates the block and sets its result as future's value fulfilling, if the block raises + # an exception the future rejects with it. + # + # @return [self] + # @yield [*args] to the block. + # @yieldreturn [Object] value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1395 + def evaluate_to(*args, &block); end + + # Evaluates the block and sets its result as future's value fulfilling, if the block raises + # an exception the future rejects with it. + # + # @raise [Exception] also raise reason on rejection. + # @return [self] + # @yield [*args] to the block. + # @yieldreturn [Object] value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1406 + def evaluate_to!(*args, &block); end + + # Makes the future fulfilled with `value`, + # which triggers all dependent futures. + # + # @param value [Object] + # @param raise_on_reassign [Boolean] should method raise exception if already resolved + # @param reserved [true, false] Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1375 + def fulfill(value, raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Behaves as {Future#reason} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @return [Exception, timeout_value, nil] + # @see Future#reason + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1503 + def reason(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Makes the future rejected with `reason`, + # which triggers all dependent futures. + # + # @param reason [Object] + # @param raise_on_reassign [Boolean] should method raise exception if already resolved + # @param reserved [true, false] Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1385 + def reject(reason, raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Makes the future resolved with result of triplet `fulfilled?`, `value`, `reason`, + # which triggers all dependent futures. + # + # @param fulfilled [true, false] + # @param value [Object] + # @param reason [Object] + # @param raise_on_reassign [Boolean] should method raise exception if already resolved + # @param reserved [true, false] Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1365 + def resolve(fulfilled = T.unsafe(nil), value = T.unsafe(nil), reason = T.unsafe(nil), raise_on_reassign = T.unsafe(nil), reserved = T.unsafe(nil)); end + + # Behaves as {Future#result} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @return [::Array(Boolean, Object, Exception), nil] + # @see Future#result + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1524 + def result(timeout = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Behaves as {Future#value} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @return [Object, timeout_value, nil] + # @see Future#value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1459 + def value(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Behaves as {Future#value!} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @raise [Exception] {#reason} on rejection + # @return [Object, timeout_value, nil] + # @see Future#value! + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1481 + def value!(timeout = T.unsafe(nil), timeout_value = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Behaves as {AbstractEventFuture#wait} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @return [self, true, false] + # @see AbstractEventFuture#wait + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1421 + def wait(timeout = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Behaves as {Future#wait!} but has one additional optional argument + # resolve_on_timeout. + # + # @param resolve_on_timeout [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + # @raise [Exception] {#reason} on rejection + # @return [self, true, false] + # @see Future#wait! + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1438 + def wait!(timeout = T.unsafe(nil), resolve_on_timeout = T.unsafe(nil)); end + + # Creates new future wrapping receiver, effectively hiding the resolve method and similar. + # + # @return [Future] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1542 + def with_hidden_resolvable; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1606 +class Concurrent::Promises::ResolvableFuturePromise < ::Concurrent::Promises::AbstractPromise + # @return [ResolvableFuturePromise] a new instance of ResolvableFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1607 + def initialize(default_executor); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1592 + def evaluate_to(*args, block); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1909 +class Concurrent::Promises::RunFuturePromise < ::Concurrent::Promises::AbstractFlatPromise + # @return [RunFuturePromise] a new instance of RunFuturePromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1913 + def initialize(delayed, blockers_count, default_executor, run_test); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1918 + def process_on_blocker_resolution(future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2114 +class Concurrent::Promises::ScheduledPromise < ::Concurrent::Promises::InnerPromise + # @return [ScheduledPromise] a new instance of ScheduledPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2125 + def initialize(default_executor, intended_time); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2119 + def inspect; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2115 + def intended_time; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1730 +class Concurrent::Promises::ThenPromise < ::Concurrent::Promises::BlockedTaskPromise + # @return [ThenPromise] a new instance of ThenPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1733 + def initialize(delayed, blockers_count, default_executor, executor, args, &task); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1737 + def on_resolvable(resolved_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1940 +class Concurrent::Promises::ZipEventEventPromise < ::Concurrent::Promises::BlockedPromise + # @return [ZipEventEventPromise] a new instance of ZipEventEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1941 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1947 + def on_resolvable(resolved_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2031 +class Concurrent::Promises::ZipEventsPromise < ::Concurrent::Promises::BlockedPromise + # @return [ZipEventsPromise] a new instance of ZipEventsPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2035 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2041 + def on_resolvable(resolved_future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1952 +class Concurrent::Promises::ZipFutureEventPromise < ::Concurrent::Promises::BlockedPromise + # @return [ZipFutureEventPromise] a new instance of ZipFutureEventPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1953 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1967 + def on_resolvable(resolved_future, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1960 + def process_on_blocker_resolution(future, index); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#1996 +class Concurrent::Promises::ZipFuturesPromise < ::Concurrent::Promises::BlockedPromise + # @return [ZipFuturesPromise] a new instance of ZipFuturesPromise + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2000 + def initialize(delayed, blockers_count, default_executor); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2013 + def on_resolvable(resolved_future, index); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/promises.rb#2007 + def process_on_blocker_resolution(future, index); end +end + +# Methods form module A included to a module B, which is already included into class C, +# will not be visible in the C class. If this module is extended to B then A's methods +# are correctly made visible to C. +# +# @example +# module A +# def a +# :a +# end +# end +# +# module B1 +# end +# +# class C1 +# include B1 +# end +# +# module B2 +# extend Concurrent::ReInclude +# end +# +# class C2 +# include B2 +# end +# +# B1.send :include, A +# B2.send :include, A +# +# C1.new.respond_to? :a # => false +# C2.new.respond_to? :a # => true +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/re_include.rb#36 +module Concurrent::ReInclude + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/re_include.rb#44 + def extended(base); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/re_include.rb#50 + def include(*modules); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/re_include.rb#38 + def included(base); end +end + +# Ruby read-write lock implementation +# +# Allows any number of concurrent readers, but only one concurrent writer +# (And if the "write" lock is taken, any readers who come along will have to wait) +# +# If readers are already active when a writer comes along, the writer will wait for +# all the readers to finish before going ahead. +# Any additional readers that come when the writer is already waiting, will also +# wait (so writers are not starved). +# +# This implementation is based on `java.util.concurrent.ReentrantReadWriteLock`. +# +# @example +# lock = Concurrent::ReadWriteLock.new +# lock.with_read_lock { data.retrieve } +# lock.with_write_lock { data.modify! } +# @note Do **not** try to acquire the write lock while already holding a read lock +# **or** try to acquire the write lock while you already have it. +# This will lead to deadlock +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html java.util.concurrent.ReentrantReadWriteLock +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#31 +class Concurrent::ReadWriteLock < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `ReadWriteLock` in the unlocked state. + # + # @return [ReadWriteLock] a new instance of ReadWriteLock + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#59 + def initialize; end + + # Acquire a read lock. If a write lock has been acquired will block until + # it is released. Will not block if other read locks have been acquired. + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#111 + def acquire_read_lock; end + + # Acquire a write lock. Will block and wait for all active readers and writers. + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of writers + # is exceeded. + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#160 + def acquire_write_lock; end + + # Queries whether any threads are waiting to acquire the read or write lock. + # + # @return [Boolean] true if any threads are waiting for a lock else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#214 + def has_waiters?; end + + # Release a previously acquired read lock. + # + # @return [Boolean] true if the lock is successfully released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#140 + def release_read_lock; end + + # Release a previously acquired write lock. + # + # @return [Boolean] true if the lock is successfully released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#196 + def release_write_lock; end + + # Execute a block operation within a read lock. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Object] the result of the block operation. + # @yield the task to be performed within the lock. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#75 + def with_read_lock; end + + # Execute a block operation within a write lock. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Object] the result of the block operation. + # @yield the task to be performed within the lock. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#94 + def with_write_lock; end + + # Queries if the write lock is held by any thread. + # + # @return [Boolean] true if the write lock is held else false` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#207 + def write_locked?; end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#246 + def max_readers?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#251 + def max_writers?(c = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#221 + def running_readers(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#226 + def running_readers?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#231 + def running_writer?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#241 + def waiting_writer?(c = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#236 + def waiting_writers(c = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#40 +Concurrent::ReadWriteLock::MAX_READERS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#43 +Concurrent::ReadWriteLock::MAX_WRITERS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#37 +Concurrent::ReadWriteLock::RUNNING_WRITER = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb#34 +Concurrent::ReadWriteLock::WAITING_WRITER = T.let(T.unsafe(nil), Integer) + +# Re-entrant read-write lock implementation +# +# Allows any number of concurrent readers, but only one concurrent writer +# (And while the "write" lock is taken, no read locks can be obtained either. +# Hence, the write lock can also be called an "exclusive" lock.) +# +# If another thread has taken a read lock, any thread which wants a write lock +# will block until all the readers release their locks. However, once a thread +# starts waiting to obtain a write lock, any additional readers that come along +# will also wait (so writers are not starved). +# +# A thread can acquire both a read and write lock at the same time. A thread can +# also acquire a read lock OR a write lock more than once. Only when the read (or +# write) lock is released as many times as it was acquired, will the thread +# actually let it go, allowing other threads which might have been waiting +# to proceed. Therefore the lock can be upgraded by first acquiring +# read lock and then write lock and that the lock can be downgraded by first +# having both read and write lock a releasing just the write lock. +# +# If both read and write locks are acquired by the same thread, it is not strictly +# necessary to release them in the same order they were acquired. In other words, +# the following code is legal: +# +# This implementation was inspired by `java.util.concurrent.ReentrantReadWriteLock`. +# +# @example +# lock = Concurrent::ReentrantReadWriteLock.new +# lock.acquire_write_lock +# lock.acquire_read_lock +# lock.release_write_lock +# # At this point, the current thread is holding only a read lock, not a write +# # lock. So other threads can take read locks, but not a write lock. +# lock.release_read_lock +# # Now the current thread is not holding either a read or write lock, so +# # another thread could potentially acquire a write lock. +# @example +# lock = Concurrent::ReentrantReadWriteLock.new +# lock.with_read_lock { data.retrieve } +# lock.with_write_lock { data.modify! } +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html java.util.concurrent.ReentrantReadWriteLock +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#53 +class Concurrent::ReentrantReadWriteLock < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `ReentrantReadWriteLock` in the unlocked state. + # + # @return [ReentrantReadWriteLock] a new instance of ReentrantReadWriteLock + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#109 + def initialize; end + + # Acquire a read lock. If a write lock is held by another thread, will block + # until it is released. + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#162 + def acquire_read_lock; end + + # Acquire a write lock. Will block and wait for all active readers and writers. + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of writers + # is exceeded. + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#257 + def acquire_write_lock; end + + # Release a previously acquired read lock. + # + # @return [Boolean] true if the lock is successfully released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#236 + def release_read_lock; end + + # Release a previously acquired write lock. + # + # @return [Boolean] true if the lock is successfully released + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#329 + def release_write_lock; end + + # Try to acquire a read lock and return true if we succeed. If it cannot be + # acquired immediately, return false. + # + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#215 + def try_read_lock; end + + # Try to acquire a write lock and return true if we succeed. If it cannot be + # acquired immediately, return false. + # + # @return [Boolean] true if the lock is successfully acquired + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#310 + def try_write_lock; end + + # Execute a block operation within a read lock. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Object] the result of the block operation. + # @yield the task to be performed within the lock. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#126 + def with_read_lock; end + + # Execute a block operation within a write lock. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + # @return [Object] the result of the block operation. + # @yield the task to be performed within the lock. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#145 + def with_write_lock; end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#370 + def max_readers?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#375 + def max_writers?(c = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#345 + def running_readers(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#350 + def running_readers?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#355 + def running_writer?(c = T.unsafe(nil)); end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#365 + def waiting_or_running_writer?(c = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#360 + def waiting_writers(c = T.unsafe(nil)); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#94 +Concurrent::ReentrantReadWriteLock::MAX_READERS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#96 +Concurrent::ReentrantReadWriteLock::MAX_WRITERS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#84 +Concurrent::ReentrantReadWriteLock::READER_BITS = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#102 +Concurrent::ReentrantReadWriteLock::READ_LOCK_MASK = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#92 +Concurrent::ReentrantReadWriteLock::RUNNING_WRITER = T.let(T.unsafe(nil), Integer) + +# Used with @Counter: +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#90 +Concurrent::ReentrantReadWriteLock::WAITING_WRITER = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#86 +Concurrent::ReentrantReadWriteLock::WRITER_BITS = T.let(T.unsafe(nil), Integer) + +# Used with @HeldCount: +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#100 +Concurrent::ReentrantReadWriteLock::WRITE_LOCK_HELD = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb#104 +Concurrent::ReentrantReadWriteLock::WRITE_LOCK_MASK = T.let(T.unsafe(nil), Integer) + +# Raised by an `Executor` when it is unable to process a given task, +# possibly because of a reject policy or other internal error. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#48 +class Concurrent::RejectedExecutionError < ::Concurrent::Error; end + +# Raised when any finite resource, such as a lock counter, exceeds its +# maximum limit/threshold. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#52 +class Concurrent::ResourceLimitError < ::Concurrent::Error; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#129 +class Concurrent::RubyExchanger < ::Concurrent::AbstractExchanger + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [RubyExchanger] a new instance of RubyExchanger + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#159 + def initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_slot(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def slot; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def slot=(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_slot(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_slot(&block); end + + private + + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # @param value [Object] the value to exchange with another thread + # @param timeout [Numeric, nil] in seconds, `nil` blocks indefinitely + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#170 + def do_exchange(value, timeout); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#138 +class Concurrent::RubyExchanger::Node < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [Node] a new instance of Node + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#142 + def initialize(item); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#137 + def __initialize_atomic_fields__; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#105 + def compare_and_set_value(expected, value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#153 + def item; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/exchanger.rb#149 + def latch; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#101 + def swap_value(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#109 + def update_value(&block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#93 + def value; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#97 + def value=(value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#8 +class Concurrent::RubyExecutorService < ::Concurrent::AbstractExecutorService + # @return [RubyExecutorService] a new instance of RubyExecutorService + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#11 + def initialize(*args, &block); end + + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#42 + def kill; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#17 + def post(*args, &task); end + + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#33 + def shutdown; end + + # Block until executor shutdown is complete or until `timeout` seconds have + # passed. + # + # @note Does not initiate shutdown or termination. Either `shutdown` or `kill` + # must be called before this method (or on another thread). + # @param timeout [Integer] the maximum number of seconds to wait for shutdown to complete + # @return [Boolean] `true` if shutdown complete or false on `timeout` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#52 + def wait_for_termination(timeout = T.unsafe(nil)); end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#70 + def ns_running?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#78 + def ns_shutdown?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#66 + def ns_shutdown_execution; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#74 + def ns_shuttingdown?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#58 + def stop_event; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#62 + def stopped_event; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb#8 +class Concurrent::RubySingleThreadExecutor < ::Concurrent::RubyThreadPoolExecutor + # @return [RubySingleThreadExecutor] a new instance of RubySingleThreadExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb#11 + def initialize(opts = T.unsafe(nil)); end +end + +# **Thread Pool Options** +# +# Thread pools support several configuration options: +# +# * `idletime`: The number of seconds that a thread may be idle before being reclaimed. +# * `name`: The name of the executor (optional). Printed in the executor's `#to_s` output and +# a `-worker-` name is given to its threads if supported by used Ruby +# implementation. `` is uniq for each thread. +# * `max_queue`: The maximum number of tasks that may be waiting in the work queue at +# any one time. When the queue size reaches `max_queue` and no new threads can be created, +# subsequent tasks will be rejected in accordance with the configured `fallback_policy`. +# * `auto_terminate`: When true (default), the threads started will be marked as daemon. +# * `fallback_policy`: The policy defining how rejected tasks are handled. +# +# Three fallback policies are supported: +# +# * `:abort`: Raise a `RejectedExecutionError` exception and discard the task. +# * `:discard`: Discard the task and return false. +# * `:caller_runs`: Execute the task on the calling thread. +# +# **Shutting Down Thread Pools** +# +# Killing a thread pool while tasks are still being processed, either by calling +# the `#kill` method or at application exit, will have unpredictable results. There +# is no way for the thread pool to know what resources are being used by the +# in-progress tasks. When those tasks are killed the impact on those resources +# cannot be predicted. The *best* practice is to explicitly shutdown all thread +# pools using the provided methods: +# +# * Call `#shutdown` to initiate an orderly termination of all in-progress tasks +# * Call `#wait_for_termination` with an appropriate timeout interval an allow +# the orderly shutdown to complete +# * Call `#kill` *only when* the thread pool fails to shutdown in the allotted time +# +# On some runtime platforms (most notably the JVM) the application will not +# exit until all thread pools have been shutdown. To prevent applications from +# "hanging" on exit, all threads can be marked as daemon according to the +# `:auto_terminate` option. +# +# ```ruby +# pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon +# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon +# ``` +# +# @note Failure to properly shutdown a thread pool can lead to unpredictable results. +# Please read *Shutting Down Thread Pools* for more information. +# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface +# @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean- +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#12 +class Concurrent::RubyThreadPoolExecutor < ::Concurrent::RubyExecutorService + # @return [RubyThreadPoolExecutor] a new instance of RubyThreadPoolExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#45 + def initialize(opts = T.unsafe(nil)); end + + # The number of threads that are actively executing tasks. + # + # @return [Integer] The number of threads that are actively executing tasks. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#65 + def active_count; end + + # Does the task queue have a maximum size? + # + # @return [Boolean] True if the task queue has a maximum size else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#72 + def can_overflow?; end + + # The number of tasks that have been completed by the pool since construction. + # + # @return [Integer] The number of tasks that have been completed by the pool since construction. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#60 + def completed_task_count; end + + # The number of seconds that a thread may be idle before being reclaimed. + # + # @return [Integer] The number of seconds that a thread may be idle before being reclaimed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#36 + def idletime; end + + # The largest number of threads that have been created in the pool since construction. + # + # @return [Integer] The largest number of threads that have been created in the pool since construction. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#50 + def largest_length; end + + # The number of threads currently in the pool. + # + # @return [Integer] The number of threads currently in the pool. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#77 + def length; end + + # The maximum number of threads that may be created in the pool. + # + # @return [Integer] The maximum number of threads that may be created in the pool. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#30 + def max_length; end + + # The maximum number of tasks that may be waiting in the work queue at any one time. + # When the queue size reaches `max_queue` subsequent tasks will be rejected in + # accordance with the configured `fallback_policy`. + # + # @return [Integer] The maximum number of tasks that may be waiting in the work queue at any one time. + # When the queue size reaches `max_queue` subsequent tasks will be rejected in + # accordance with the configured `fallback_policy`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#39 + def max_queue; end + + # The minimum number of threads that may be retained in the pool. + # + # @return [Integer] The minimum number of threads that may be retained in the pool. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#33 + def min_length; end + + # Prune the thread pool of unneeded threads + # + # What is being pruned is controlled by the min_threads and idletime + # parameters passed at pool creation time + # + # This is a no-op on some pool implementation (e.g. the Java one). The Ruby + # pool will auto-prune each time a new job is posted. You will need to call + # this method explicitely in case your application post jobs in bursts (a + # lot of jobs and then nothing for long periods) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#118 + def prune_pool; end + + # The number of tasks in the queue awaiting execution. + # + # @return [Integer] The number of tasks in the queue awaiting execution. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#82 + def queue_length; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#103 + def ready_worker(worker, last_message); end + + # Number of tasks that may be enqueued before reaching `max_queue` and rejecting + # new tasks. A value of -1 indicates that the queue may grow without bound. + # + # @return [Integer] Number of tasks that may be enqueued before reaching `max_queue` and rejecting + # new tasks. A value of -1 indicates that the queue may grow without bound. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#87 + def remaining_capacity; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#98 + def remove_busy_worker(worker); end + + # The number of tasks that have been scheduled for execution on the pool since construction. + # + # @return [Integer] The number of tasks that have been scheduled for execution on the pool since construction. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#55 + def scheduled_task_count; end + + # Whether or not a value of 0 for :max_queue option means the queue must perform direct hand-off or rather unbounded queue. + # + # @return [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#42 + def synchronous; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#108 + def worker_died(worker); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#113 + def worker_task_completed; end + + private + + # creates new worker which has to receive work to do after it's added + # + # @return [nil, Worker] nil of max capacity is reached + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#241 + def ns_add_busy_worker; end + + # tries to assign task to a worker, tries to get one from @ready or to create new one + # + # @return [true, false] if task is assigned to a worker + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#201 + def ns_assign_worker(*args, &task); end + + # tries to enqueue task + # + # @return [true, false] if enqueued + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#219 + def ns_enqueue(*args, &task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#160 + def ns_execute(*args, &task); end + + # @raise [ArgumentError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#125 + def ns_initialize(opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#189 + def ns_kill_execution; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#155 + def ns_limited_queue?; end + + # try oldest worker if it is idle for enough time, it's returned back at the start + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#280 + def ns_prune_pool; end + + # handle ready worker, giving it new job or assigning back to @ready + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#253 + def ns_ready_worker(worker, last_message, success = T.unsafe(nil)); end + + # removes a worker which is not in not tracked in @ready + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#271 + def ns_remove_busy_worker(worker); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#296 + def ns_reset_if_forked; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#174 + def ns_shutdown_execution; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#231 + def ns_worker_died(worker); end +end + +# Default maximum number of threads that will be created in the pool. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#15 +Concurrent::RubyThreadPoolExecutor::DEFAULT_MAX_POOL_SIZE = T.let(T.unsafe(nil), Integer) + +# Default maximum number of tasks that may be added to the task queue. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#21 +Concurrent::RubyThreadPoolExecutor::DEFAULT_MAX_QUEUE_SIZE = T.let(T.unsafe(nil), Integer) + +# Default minimum number of threads that will be retained in the pool. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#18 +Concurrent::RubyThreadPoolExecutor::DEFAULT_MIN_POOL_SIZE = T.let(T.unsafe(nil), Integer) + +# Default value of the :synchronous option. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#27 +Concurrent::RubyThreadPoolExecutor::DEFAULT_SYNCHRONOUS = T.let(T.unsafe(nil), FalseClass) + +# Default maximum number of seconds a thread in the pool may remain idle +# before being reclaimed. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#24 +Concurrent::RubyThreadPoolExecutor::DEFAULT_THREAD_IDLETIMEOUT = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#310 +class Concurrent::RubyThreadPoolExecutor::Worker + include ::Logger::Severity + include ::Concurrent::Concern::Logging + + # @return [Worker] a new instance of Worker + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#313 + def initialize(pool, id); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#324 + def <<(message); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#332 + def kill; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#328 + def stop; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#338 + def create_worker(queue, pool, idletime); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb#358 + def run_task(pool, task, args); end +end + +# A simple utility class that executes a callable and returns and array of three elements: +# success - indicating if the callable has been executed without errors +# value - filled by the callable result if it has been executed without errors, nil otherwise +# reason - the error risen by the callable if it has been executed with errors, nil otherwise +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb#9 +class Concurrent::SafeTaskExecutor < ::Concurrent::Synchronization::LockableObject + # @return [SafeTaskExecutor] a new instance of SafeTaskExecutor + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb#11 + def initialize(task, opts = T.unsafe(nil)); end + + # @return [Array] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb#18 + def execute(*args); end +end + +# `ScheduledTask` is a close relative of `Concurrent::Future` but with one +# important difference: A `Future` is set to execute as soon as possible +# whereas a `ScheduledTask` is set to execute after a specified delay. This +# implementation is loosely based on Java's +# [ScheduledExecutorService](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html). +# It is a more feature-rich variant of {Concurrent.timer}. +# +# The *intended* schedule time of task execution is set on object construction +# with the `delay` argument. The delay is a numeric (floating point or integer) +# representing a number of seconds in the future. Any other value or a numeric +# equal to or less than zero will result in an exception. The *actual* schedule +# time of task execution is set when the `execute` method is called. +# +# The constructor can also be given zero or more processing options. Currently +# the only supported options are those recognized by the +# [Dereferenceable](Dereferenceable) module. +# +# The final constructor argument is a block representing the task to be performed. +# If no block is given an `ArgumentError` will be raised. +# +# **States** +# +# `ScheduledTask` mixes in the [Obligation](Obligation) module thus giving it +# "future" behavior. This includes the expected lifecycle states. `ScheduledTask` +# has one additional state, however. While the task (block) is being executed the +# state of the object will be `:processing`. This additional state is necessary +# because it has implications for task cancellation. +# +# **Cancellation** +# +# A `:pending` task can be cancelled using the `#cancel` method. A task in any +# other state, including `:processing`, cannot be cancelled. The `#cancel` +# method returns a boolean indicating the success of the cancellation attempt. +# A cancelled `ScheduledTask` cannot be restarted. It is immutable. +# +# **Obligation and Observation** +# +# The result of a `ScheduledTask` can be obtained either synchronously or +# asynchronously. `ScheduledTask` mixes in both the [Obligation](Obligation) +# module and the +# [Observable](http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html) +# module from the Ruby standard library. With one exception `ScheduledTask` +# behaves identically to [Future](Observable) with regard to these modules. +# +# @example Basic usage +# +# require 'concurrent/scheduled_task' +# require 'csv' +# require 'open-uri' +# +# class Ticker +# def get_year_end_closing(symbol, year, api_key) +# uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv" +# data = [] +# csv = URI.parse(uri).read +# if csv.include?('call frequency') +# return :rate_limit_exceeded +# end +# CSV.parse(csv, headers: true) do |row| +# data << row['close'].to_f if row['timestamp'].include?(year.to_s) +# end +# year_end = data.first +# year_end +# rescue => e +# p e +# end +# end +# +# api_key = ENV['ALPHAVANTAGE_KEY'] +# abort(error_message) unless api_key +# +# # Future +# price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013, api_key) } +# price.state #=> :pending +# price.pending? #=> true +# price.value(0) #=> nil (does not block) +# +# sleep(1) # do other stuff +# +# price.value #=> 63.65 (after blocking if necessary) +# price.state #=> :fulfilled +# price.fulfilled? #=> true +# price.value #=> 63.65 +# @example Successful task execution +# +# task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' } +# task.state #=> :unscheduled +# task.execute +# task.state #=> pending +# +# # wait for it... +# sleep(3) +# +# task.unscheduled? #=> false +# task.pending? #=> false +# task.fulfilled? #=> true +# task.rejected? #=> false +# task.value #=> 'What does the fox say?' +# @example One line creation and execution +# +# task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' }.execute +# task.state #=> pending +# +# task = Concurrent::ScheduledTask.execute(2){ 'What do you get when you multiply 6 by 9?' } +# task.state #=> pending +# @example Failed task execution +# +# task = Concurrent::ScheduledTask.execute(2){ raise StandardError.new('Call me maybe?') } +# task.pending? #=> true +# +# # wait for it... +# sleep(3) +# +# task.unscheduled? #=> false +# task.pending? #=> false +# task.fulfilled? #=> false +# task.rejected? #=> true +# task.value #=> nil +# task.reason #=> # +# @example Task execution with observation +# +# observer = Class.new{ +# def update(time, value, reason) +# puts "The task completed at #{time} with value '#{value}'" +# end +# }.new +# +# task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' } +# task.add_observer(observer) +# task.execute +# task.pending? #=> true +# +# # wait for it... +# sleep(3) +# +# #>> The task completed at 2013-11-07 12:26:09 -0500 with value 'What does the fox say?' +# @see Concurrent.timer +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#158 +class Concurrent::ScheduledTask < ::Concurrent::IVar + include ::Comparable + + # Schedule a task for execution at a specified future time. + # + # @option opts + # @param delay [Float] the number of seconds to wait for before executing the task + # @param opts [Hash] a customizable set of options + # @raise [ArgumentError] When no block is given + # @raise [ArgumentError] When given a time that is in the past + # @return [ScheduledTask] a new instance of ScheduledTask + # @yield the task to be performed + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#178 + def initialize(delay, opts = T.unsafe(nil), &task); end + + # Comparator which orders by schedule time. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#213 + def <=>(other); end + + # Cancel this task and prevent it from executing. A task can only be + # cancelled if it is pending or unscheduled. + # + # @return [Boolean] true if successfully cancelled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#235 + def cancel; end + + # Has the task been cancelled? + # + # @return [Boolean] true if the task is in the given state else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#220 + def cancelled?; end + + # Execute an `:unscheduled` `ScheduledTask`. Immediately sets the state to `:pending` + # and starts counting down toward execution. Does nothing if the `ScheduledTask` is + # in any state other than `:unscheduled`. + # + # @return [ScheduledTask] a reference to `self` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#273 + def execute; end + + # The executor on which to execute the task. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#163 + def executor; end + + # The `delay` value given at instanciation. + # + # @return [Float] the initial delay. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#199 + def initial_delay; end + + # Execute the task. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#297 + def process_task; end + + # In the task execution in progress? + # + # @return [Boolean] true if the task is in the given state else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#227 + def processing?; end + + # Reschedule the task using the given delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @param delay [Float] the number of seconds to wait for before executing the task + # @raise [ArgumentError] When given a time that is in the past + # @return [Boolean] true if successfully rescheduled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#262 + def reschedule(delay); end + + # Reschedule the task using the original delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @return [Boolean] true if successfully rescheduled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#250 + def reset; end + + # The monotonic time at which the the task is scheduled to be executed. + # + # @return [Float] the schedule time or nil if `unscheduled` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#206 + def schedule_time; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#135 + def fail(reason = T.unsafe(nil)); end + + # Reschedule the task using the given delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @param delay [Float] the number of seconds to wait for before executing the task + # @return [Boolean] true if successfully rescheduled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#326 + def ns_reschedule(delay); end + + # Schedule the task using the given delay and the current time. + # + # @param delay [Float] the number of seconds to wait for before executing the task + # @return [Boolean] true if successfully rescheduled else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#312 + def ns_schedule(delay); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#113 + def set(value = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/ivar.rb#145 + def try_set(value = T.unsafe(nil), &block); end + + class << self + # Create a new `ScheduledTask` object with the given block, execute it, and return the + # `:pending` object. + # + # @param delay [Float] the number of seconds to wait for before executing the task + # @raise [ArgumentError] if no block is given + # @return [ScheduledTask] the newly created `ScheduledTask` in the `:pending` state + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/scheduled_task.rb#290 + def execute(delay, opts = T.unsafe(nil), &task); end + end +end + +# A counting semaphore. Conceptually, a semaphore maintains a set of +# permits. Each {#acquire} blocks if necessary until a permit is +# available, and then takes it. Each {#release} adds a permit, potentially +# releasing a blocking acquirer. +# However, no actual permit objects are used; the Semaphore just keeps a +# count of the number available and acts accordingly. +# Alternatively, permits may be acquired within a block, and automatically +# released after the block finishes executing. +# +# @example +# semaphore = Concurrent::Semaphore.new(2) +# +# t1 = Thread.new do +# semaphore.acquire +# puts "Thread 1 acquired semaphore" +# end +# +# t2 = Thread.new do +# semaphore.acquire +# puts "Thread 2 acquired semaphore" +# end +# +# t3 = Thread.new do +# semaphore.acquire +# puts "Thread 3 acquired semaphore" +# end +# +# t4 = Thread.new do +# sleep(2) +# puts "Thread 4 releasing semaphore" +# semaphore.release +# end +# +# [t1, t2, t3, t4].each(&:join) +# +# # prints: +# # Thread 3 acquired semaphore +# # Thread 2 acquired semaphore +# # Thread 4 releasing semaphore +# # Thread 1 acquired semaphore +# @example +# semaphore = Concurrent::Semaphore.new(1) +# +# puts semaphore.available_permits +# semaphore.acquire do +# puts semaphore.available_permits +# end +# puts semaphore.available_permits +# +# # prints: +# # 1 +# # 0 +# # 1 +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/semaphore.rb#161 +class Concurrent::Semaphore < ::Concurrent::MutexSemaphore; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/semaphore.rb#96 +Concurrent::SemaphoreImplementation = Concurrent::MutexSemaphore + +# Indicates that the including `ExecutorService` guarantees +# that all operations will occur in the order they are post and that no +# two operations may occur simultaneously. This module provides no +# functionality and provides no guarantees. That is the responsibility +# of the including class. This module exists solely to allow the including +# object to be interrogated for its serialization status. +# +# @example +# class Foo +# include Concurrent::SerialExecutor +# end +# +# foo = Foo.new +# +# foo.is_a? Concurrent::ExecutorService #=> true +# foo.is_a? Concurrent::SerialExecutor #=> true +# foo.serialized? #=> true +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb#24 +module Concurrent::SerialExecutorService + include ::Logger::Severity + include ::Concurrent::Concern::Logging + include ::Concurrent::ExecutorService + + # Does this executor guarantee serialization of its operations? + # + # @note Always returns `true` + # @return [Boolean] True if the executor guarantees that all operations + # will be post in the order they are received and no two operations may + # occur simultaneously. Else false. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb#30 + def serialized?; end +end + +# Ensures passed jobs in a serialized order never running at the same time. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#8 +class Concurrent::SerializedExecution < ::Concurrent::Synchronization::LockableObject + include ::Logger::Severity + include ::Concurrent::Concern::Logging + + # @return [SerializedExecution] a new instance of SerializedExecution + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#11 + def initialize; end + + # Submit a task to the executor for asynchronous processing. + # + # @param executor [Executor] to be used for this job + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#34 + def post(executor, *args, &task); end + + # As {#post} but allows to submit multiple tasks at once, it's guaranteed that they will not + # be interleaved by other tasks. + # + # @param posts [Array, Proc)>] array of triplets where + # first is a {ExecutorService}, second is array of args for task, third is a task (Proc) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#44 + def posts(posts); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#75 + def call_job(job); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#70 + def ns_initialize; end + + # ensures next job is executed if any is stashed + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#95 + def work(job); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#16 +class Concurrent::SerializedExecution::Job < ::Struct + # Returns the value of attribute args + # + # @return [Object] the current value of args + def args; end + + # Sets the attribute args + # + # @param value [Object] the value to set the attribute args to. + # @return [Object] the newly set value + def args=(_); end + + # Returns the value of attribute block + # + # @return [Object] the current value of block + def block; end + + # Sets the attribute block + # + # @param value [Object] the value to set the attribute block to. + # @return [Object] the newly set value + def block=(_); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution.rb#17 + def call; end + + # Returns the value of attribute executor + # + # @return [Object] the current value of executor + def executor; end + + # Sets the attribute executor + # + # @param value [Object] the value to set the attribute executor to. + # @return [Object] the newly set value + def executor=(_); end + + class << self + def [](*_arg0); end + def inspect; end + def keyword_init?; end + def members; end + def new(*_arg0); end + end +end + +# A wrapper/delegator for any `ExecutorService` that +# guarantees serialized execution of tasks. +# +# @see [SimpleDelegator](http://www.ruby-doc.org/stdlib-2.1.2/libdoc/delegate/rdoc/SimpleDelegator.html) +# @see Concurrent::SerializedExecution +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb#12 +class Concurrent::SerializedExecutionDelegator < ::SimpleDelegator + include ::Logger::Severity + include ::Concurrent::Concern::Logging + include ::Concurrent::ExecutorService + include ::Concurrent::SerialExecutorService + + # @return [SerializedExecutionDelegator] a new instance of SerializedExecutionDelegator + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb#15 + def initialize(executor); end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb#22 + def post(*args, &task); end +end + +# A thread-safe subclass of Set. This version locks against the object +# itself for every method call, ensuring only one thread can be reading +# or writing at a time. This includes iteration methods like `#each`. +# +# @note `a += b` is **not** a **thread-safe** operation on +# `Concurrent::Set`. It reads Set `a`, then it creates new `Concurrent::Set` +# which is union of `a` and `b`, then it writes the union to `a`. +# The read and write are independent operations they do not form a single atomic +# operation therefore when two `+=` operations are executed concurrently updates +# may be lost. Use `#merge` instead. +# @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/set.rb#61 +class Concurrent::Set < ::Concurrent::CRubySet; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/set.rb#23 +Concurrent::SetImplementation = Concurrent::CRubySet + +# An thread-safe, write-once variation of Ruby's standard `Struct`. +# Each member can have its value set at most once, either at construction +# or any time thereafter. Attempting to assign a value to a member +# that has already been set will result in a `Concurrent::ImmutabilityError`. +# +# @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` +# @see http://en.wikipedia.org/wiki/Final_(Java) Java `final` keyword +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#14 +module Concurrent::SettableStruct + include ::Concurrent::Synchronization::AbstractStruct + + # Equality + # + # @return [Boolean] true if other has the same struct subclass and has + # equal member values (according to `Object#==`) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#50 + def ==(other); end + + # Attribute Reference + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the member does not exist + # @raise [IndexError] if the index is out of range. + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#45 + def [](member); end + + # Attribute Assignment + # + # Sets the value of the given struct member or the member at the given index. + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the name does not exist + # @raise [IndexError] if the index is out of range. + # @raise [Concurrent::ImmutabilityError] if the given member has already been set + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#75 + def []=(member, value); end + + # Yields the value of each struct member in order. If no block is given + # an enumerator is returned. + # + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#55 + def each(&block); end + + # Yields the name and value of each struct member in order. If no block is + # given an enumerator is returned. + # + # @yield the operation to be performed on each struct member/value pair + # @yieldparam member [Object] each struct member (in order) + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#61 + def each_pair(&block); end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#29 + def inspect; end + + # Returns a new struct containing the contents of `other` and the contents + # of `self`. If no block is specified, the value for entries with duplicate + # keys will be that of `other`. Otherwise the value for each duplicate key + # is determined by calling the block with the key, its value in `self` and + # its value in `other`. + # + # @param other [Hash] the hash from which to set the new values + # @raise [ArgumentError] of given a member that is not defined in the struct + # @return [Synchronization::AbstractStruct] a new struct with the new values + # @yield an options block for resolving duplicate keys + # @yieldparam member [String, Symbol] the name of the member which is duplicated + # @yieldparam selfvalue [Object] the value of the member in `self` + # @yieldparam othervalue [Object] the value of the member in `other` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#35 + def merge(other, &block); end + + # Yields each member value from the struct to the block and returns an Array + # containing the member values from the struct for which the given block + # returns a true value (equivalent to `Enumerable#select`). + # + # @return [Array] an array containing each value for which the block returns true + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#67 + def select(&block); end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#18 + def to_a; end + + # Returns a hash containing the names and values for the struct’s members. + # + # @return [Hash] the names and values for the struct’s members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#40 + def to_h; end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#29 + def to_s; end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#18 + def values; end + + # Returns the struct member values for each selector as an Array. + # + # A selector may be either an Integer offset or a Range of offsets (as in `Array#values_at`). + # + # @param indexes [Fixnum, Range] the index(es) from which to obatin the values (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#24 + def values_at(*indexes); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#97 + def initialize_copy(original); end + + class << self + # Factory for creating new struct classes. + # + # ``` + # new([class_name] [, member_name]+>) -> StructClass click to toggle source + # new([class_name] [, member_name]+>) {|StructClass| block } -> StructClass + # new(value, ...) -> obj + # StructClass[value, ...] -> obj + # ``` + # + # The first two forms are used to create a new struct subclass `class_name` + # that can contain a value for each member_name . This subclass can be + # used to create instances of the structure like any other Class . + # + # If the `class_name` is omitted an anonymous struct class will be created. + # Otherwise, the name of this struct will appear as a constant in the struct class, + # so it must be unique for all structs under this base class and must start with a + # capital letter. Assigning a struct class to a constant also gives the class + # the name of the constant. + # + # If a block is given it will be evaluated in the context of `StructClass`, passing + # the created class as a parameter. This is the recommended way to customize a struct. + # Subclassing an anonymous struct creates an extra anonymous class that will never be used. + # + # The last two forms create a new instance of a struct subclass. The number of value + # parameters must be less than or equal to the number of attributes defined for the + # struct. Unset parameters default to nil. Passing more parameters than number of attributes + # will raise an `ArgumentError`. + # + # @see http://ruby-doc.org/core/Struct.html#method-c-new Ruby standard library `Struct#new` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#105 + def new(*args, &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/settable_struct.rb#115 +Concurrent::SettableStruct::FACTORY = T.let(T.unsafe(nil), T.untyped) + +# An executor service in which every operation spawns a new, +# independently operating thread. +# +# This is perhaps the most inefficient executor service in this +# library. It exists mainly for testing an debugging. Thread creation +# and management is expensive in Ruby and this executor performs no +# resource pooling. This can be very beneficial during testing and +# debugging because it decouples the using code from the underlying +# executor implementation. In production this executor will likely +# lead to suboptimal performance. +# +# @note Intended for use primarily in testing and debugging. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#21 +class Concurrent::SimpleExecutorService < ::Concurrent::RubyExecutorService + # Submit a task to the executor for asynchronous processing. + # + # @param task [Proc] the asynchronous task to perform + # @return [self] returns itself + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#56 + def <<(task); end + + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#84 + def kill; end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#40 + def post(*args, &task); end + + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#62 + def running?; end + + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#77 + def shutdown; end + + # Is the executor shutdown? + # + # @return [Boolean] `true` when shutdown, `false` when shutting down or running + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#72 + def shutdown?; end + + # Is the executor shuttingdown? + # + # @return [Boolean] `true` when not running and not shutdown, else `false` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#67 + def shuttingdown?; end + + # Block until executor shutdown is complete or until `timeout` seconds have + # passed. + # + # @note Does not initiate shutdown or termination. Either `shutdown` or `kill` + # must be called before this method (or on another thread). + # @param timeout [Integer] the maximum number of seconds to wait for shutdown to complete + # @return [Boolean] `true` if shutdown complete or false on `timeout` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#91 + def wait_for_termination(timeout = T.unsafe(nil)); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#97 + def ns_initialize(*args); end + + class << self + # Submit a task to the executor for asynchronous processing. + # + # @param task [Proc] the asynchronous task to perform + # @return [self] returns itself + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#34 + def <<(task); end + + # Submit a task to the executor for asynchronous processing. + # + # @param args [Array] zero or more arguments to be passed to the task + # @raise [ArgumentError] if no task is given + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # @yield the asynchronous task to perform + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb#24 + def post(*args); end + end +end + +# A thread pool with a single thread an unlimited queue. Should the thread +# die for any reason it will be removed and replaced, thus ensuring that +# the executor will always remain viable and available to process jobs. +# +# A common pattern for background processing is to create a single thread +# on which an infinite loop is run. The thread's loop blocks on an input +# source (perhaps blocking I/O or a queue) and processes each input as it +# is received. This pattern has several issues. The thread itself is highly +# susceptible to errors during processing. Also, the thread itself must be +# constantly monitored and restarted should it die. `SingleThreadExecutor` +# encapsulates all these bahaviors. The task processor is highly resilient +# to errors from within tasks. Also, should the thread die it will +# automatically be restarted. +# +# The API and behavior of this class are based on Java's `SingleThreadExecutor`. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb#37 +class Concurrent::SingleThreadExecutor < ::Concurrent::RubySingleThreadExecutor; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb#10 +Concurrent::SingleThreadExecutorImplementation = Concurrent::RubySingleThreadExecutor + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#2 +module Concurrent::Synchronization + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb#7 + def full_memory_barrier; end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#9 +class Concurrent::Synchronization::AbstractLockableObject < ::Concurrent::Synchronization::Object + protected + + # Broadcast to all waiting threads. + # + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def broadcast + # synchronize { ns_broadcast } + # end + # ``` + # @raise [NotImplementedError] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#96 + def ns_broadcast; end + + # Signal one waiting thread. + # + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def signal + # synchronize { ns_signal } + # end + # ``` + # @raise [NotImplementedError] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#81 + def ns_signal; end + + # Wait until another thread calls #signal or #broadcast, + # spurious wake-ups can happen. + # + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def wait(timeout = nil) + # synchronize { ns_wait(timeout) } + # end + # ``` + # @param timeout [Numeric, nil] in seconds, `nil` means no timeout + # @raise [NotImplementedError] + # @return [self] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#66 + def ns_wait(timeout = T.unsafe(nil)); end + + # Wait until condition is met or timeout passes, + # protects against spurious wake-ups. + # + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def wait_until(timeout = nil, &condition) + # synchronize { ns_wait_until(timeout, &condition) } + # end + # ``` + # @param timeout [Numeric, nil] in seconds, `nil` means no timeout + # @return [true, false] if condition met + # @yield condition to be met + # @yieldreturn [true, false] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#37 + def ns_wait_until(timeout = T.unsafe(nil), &condition); end + + # @note can by made public in descendants if required by `public :synchronize` + # @raise [NotImplementedError] + # @yield runs the block synchronized against this object, + # equivalent of java's `synchronize(this) {}` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#18 + def synchronize; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#6 +class Concurrent::Synchronization::AbstractObject + # @return [AbstractObject] a new instance of AbstractObject + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#7 + def initialize; end + + # @abstract + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#13 + def full_memory_barrier; end + + class << self + # @raise [NotImplementedError] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb#17 + def attr_volatile(*names); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#6 +module Concurrent::Synchronization::AbstractStruct + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#9 + def initialize(*values); end + + # Returns the number of struct members. + # + # @return [Fixnum] the number of struct members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#19 + def length; end + + # Returns the struct members as an array of symbols. + # + # @return [Array] the struct members as an array of symbols + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#29 + def members; end + + # Returns the number of struct members. + # + # @return [Fixnum] the number of struct members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#19 + def size; end + + protected + + # Yields the value of each struct member in order. If no block is given + # an enumerator is returned. + # + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#82 + def ns_each; end + + # Yields the name and value of each struct member in order. If no block is + # given an enumerator is returned. + # + # @yield the operation to be performed on each struct member/value pair + # @yieldparam member [Object] each struct member (in order) + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#89 + def ns_each_pair; end + + # Equality + # + # @return [Boolean] true if other has the same struct subclass and has + # equal member values (according to `Object#==`) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#75 + def ns_equality(other); end + + # Attribute Reference + # + # @param member [Symbol, String, Integer] the string or symbol name of the member + # for which to obtain the value or the member's index + # @raise [NameError] if the member does not exist + # @raise [IndexError] if the index is out of range. + # @return [Object] the value of the given struct member or the member at the given index. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#59 + def ns_get(member); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#119 + def ns_initialize_copy; end + + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#105 + def ns_inspect; end + + # Returns a new struct containing the contents of `other` and the contents + # of `self`. If no block is specified, the value for entries with duplicate + # keys will be that of `other`. Otherwise the value for each duplicate key + # is determined by calling the block with the key, its value in `self` and + # its value in `other`. + # + # @param other [Hash] the hash from which to set the new values + # @raise [ArgumentError] of given a member that is not defined in the struct + # @return [Synchronization::AbstractStruct] a new struct with the new values + # @yield an options block for resolving duplicate keys + # @yieldparam member [String, Symbol] the name of the member which is duplicated + # @yieldparam selfvalue [Object] the value of the member in `self` + # @yieldparam othervalue [Object] the value of the member in `other` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#114 + def ns_merge(other, &block); end + + # Yields each member value from the struct to the block and returns an Array + # containing the member values from the struct for which the given block + # returns a true value (equivalent to `Enumerable#select`). + # + # @return [Array] an array containing each value for which the block returns true + # @yield the operation to be performed on each struct member + # @yieldparam value [Object] each struct value (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#98 + def ns_select; end + + # Returns a hash containing the names and values for the struct’s members. + # + # @return [Hash] the names and values for the struct’s members + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#52 + def ns_to_h; end + + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#38 + def ns_values; end + + # Returns the struct member values for each selector as an Array. + # + # A selector may be either an Integer offset or a Range of offsets (as in `Array#values_at`). + # + # @param indexes [Fixnum, Range] the index(es) from which to obatin the values (in order) + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#45 + def ns_values_at(indexes); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#130 + def pr_underscore(clazz); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb#141 + def define_struct_class(parent, base, name, members, &block); end + end +end + +# TODO (pitr-ch 04-Dec-2016): should be in edge +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#8 +class Concurrent::Synchronization::Condition < ::Concurrent::Synchronization::LockableObject + # @return [Condition] a new instance of Condition + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#18 + def initialize(lock); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#47 + def broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#51 + def ns_broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#43 + def ns_signal; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#27 + def ns_wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#35 + def ns_wait_until(timeout = T.unsafe(nil), &condition); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#39 + def signal; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#23 + def wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#31 + def wait_until(timeout = T.unsafe(nil), &condition); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def private_new(*args, &block); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def new(*args, &block); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#8 +module Concurrent::Synchronization::ConditionSignalling + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#16 + def ns_broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#11 + def ns_signal; end +end + +# TODO (pitr-ch 04-Dec-2016): should be in edge +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#8 +class Concurrent::Synchronization::Lock < ::Concurrent::Synchronization::LockableObject + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#31 + def broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#16 + def ns_broadcast; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#11 + def ns_signal; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#52 + def ns_wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb#37 + def ns_wait_until(timeout = T.unsafe(nil), &condition); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#25 + def signal; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#44 + def synchronize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#13 + def wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lock.rb#19 + def wait_until(timeout = T.unsafe(nil), &condition); end +end + +# Safe synchronization under any Ruby implementation. +# It provides methods like {#synchronize}, {#wait}, {#signal} and {#broadcast}. +# Provides a single layer which can improve its implementation over time without changes needed to +# the classes using it. Use {Synchronization::Object} not this abstract class. +# +# @note this object does not support usage together with +# [`Thread#wakeup`](http://ruby-doc.org/core/Thread.html#method-i-wakeup) +# and [`Thread#raise`](http://ruby-doc.org/core/Thread.html#method-i-raise). +# `Thread#sleep` and `Thread#wakeup` will work as expected but mixing `Synchronization::Object#wait` and +# `Thread#wakeup` will not work on all platforms. +# +# @see Event implementation as an example of this class use +# +# @example simple +# class AnClass < Synchronization::Object +# def initialize +# super +# synchronize { @value = 'asd' } +# end +# +# def value +# synchronize { @value } +# end +# end +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb#50 +class Concurrent::Synchronization::LockableObject < ::Concurrent::Synchronization::MutexLockableObject + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/condition.rb#57 + def new_condition; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb#11 +Concurrent::Synchronization::LockableObjectImplementation = Concurrent::Synchronization::MutexLockableObject + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#60 +class Concurrent::Synchronization::MonitorLockableObject < ::Concurrent::Synchronization::AbstractLockableObject + include ::Concurrent::Synchronization::ConditionSignalling + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [MonitorLockableObject] a new instance of MonitorLockableObject + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#65 + def initialize; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#83 + def ns_wait(timeout = T.unsafe(nil)); end + + # TODO may be a problem with lock.synchronize { lock.wait } + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#79 + def synchronize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#71 + def initialize_copy(other); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#25 +class Concurrent::Synchronization::MutexLockableObject < ::Concurrent::Synchronization::AbstractLockableObject + include ::Concurrent::Synchronization::ConditionSignalling + extend ::Concurrent::Synchronization::SafeInitialization + + # @return [MutexLockableObject] a new instance of MutexLockableObject + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#30 + def initialize; end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#52 + def ns_wait(timeout = T.unsafe(nil)); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#44 + def synchronize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb#36 + def initialize_copy(other); end +end + +# Abstract object providing final, volatile, ans CAS extensions to build other concurrent abstractions. +# - final instance variables see {Object.safe_initialization!} +# - volatile instance variables see {Object.attr_volatile} +# - volatile instance variables see {Object.attr_atomic} +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#15 +class Concurrent::Synchronization::Object < ::Concurrent::Synchronization::AbstractObject + include ::Concurrent::Synchronization::Volatile + extend ::Concurrent::Synchronization::Volatile::ClassMethods + + # Has to be called by children. + # + # @return [Object] a new instance of Object + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#28 + def initialize; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#146 + def __initialize_atomic_fields__; end + + class << self + # @return [true, false] is the attribute with name atomic? + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#125 + def atomic_attribute?(name); end + + # @param inherited [true, false] should inherited volatile with CAS fields be returned? + # @return [::Array] Returns defined volatile with CAS fields on this class. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#119 + def atomic_attributes(inherited = T.unsafe(nil)); end + + # Creates methods for reading and writing to a instance variable with + # volatile (Java) semantic as {.attr_volatile} does. + # The instance variable should be accessed oly through generated methods. + # This method generates following methods: `value`, `value=(new_value) #=> new_value`, + # `swap_value(new_value) #=> old_value`, + # `compare_and_set_value(expected, value) #=> true || false`, `update_value(&block)`. + # + # @param names [::Array] of the instance variables to be volatile with CAS. + # @return [::Array] names of defined method names. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#84 + def attr_atomic(*names); end + + # For testing purposes, quite slow. Injects assert code to new method which will raise if class instance contains + # any instance variables with CamelCase names and isn't {.safe_initialization?}. + # + # @raise when offend found + # @return [true] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#45 + def ensure_safe_initialization_when_final_fields_are_present; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#33 + def safe_initialization!; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#37 + def safe_initialization?; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/object.rb#131 + def define_initialize_atomic_fields; end + end +end + +# By extending this module, a class and all its children are marked to be constructed safely. Meaning that +# all writes (ivar initializations) are made visible to all readers of newly constructed object. It ensures +# same behaviour as Java's final fields. +# +# Due to using Kernel#extend, the module is not included again if already present in the ancestors, +# which avoids extra overhead. +# +# @example +# class AClass < Concurrent::Synchronization::Object +# extend Concurrent::Synchronization::SafeInitialization +# +# def initialize +# @AFinalValue = 'value' # published safely, #foo will never return nil +# end +# +# def foo +# @AFinalValue +# end +# end +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#28 +module Concurrent::Synchronization::SafeInitialization + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb#29 + def new(*args, &block); end +end + +# Volatile adds the attr_volatile class method when included. +# +# foo = Foo.new +# foo.bar +# => 1 +# foo.bar = 2 +# => 2 +# +# @example +# class Foo +# include Concurrent::Synchronization::Volatile +# +# attr_volatile :bar +# +# def initialize +# self.bar = 1 +# end +# end +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#28 +module Concurrent::Synchronization::Volatile + mixes_in_class_methods ::Concurrent::Synchronization::Volatile::ClassMethods + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#33 + def full_memory_barrier; end + + class << self + # @private + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#29 + def included(base); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#37 +module Concurrent::Synchronization::Volatile::ClassMethods + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/synchronization/volatile.rb#39 + def attr_volatile(*names); end +end + +# This class provides a trivial way to synchronize all calls to a given object +# by wrapping it with a `Delegator` that performs `Monitor#enter/exit` calls +# around the delegated `#send`. Example: +# +# array = [] # not thread-safe on many impls +# array = SynchronizedDelegator.new([]) # thread-safe +# +# A simple `Monitor` provides a very coarse-grained way to synchronize a given +# object, in that it will cause synchronization for methods that have no need +# for it, but this is a trivial way to get thread-safety where none may exist +# currently on some implementations. +# +# This class is currently being considered for inclusion into stdlib, via +# https://bugs.ruby-lang.org/issues/8556 +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#21 +class Concurrent::SynchronizedDelegator < ::SimpleDelegator + # @return [SynchronizedDelegator] a new instance of SynchronizedDelegator + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#31 + def initialize(obj); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#36 + def method_missing(method, *args, &block); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#22 + def setup; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb#27 + def teardown; end +end + +# A `TVar` is a transactional variable - a single-element container that +# is used as part of a transaction - see `Concurrent::atomically`. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# {include:file:docs-source/tvar.md} +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#12 +class Concurrent::TVar < ::Concurrent::Synchronization::Object + extend ::Concurrent::Synchronization::SafeInitialization + + # Create a new `TVar` with an initial value. + # + # @return [TVar] a new instance of TVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#16 + def initialize(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#46 + def unsafe_lock; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#36 + def unsafe_value; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#41 + def unsafe_value=(value); end + + # Get the value of a `TVar`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#22 + def value; end + + # Set the value of a `TVar`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#29 + def value=(value); end +end + +# A `ThreadLocalVar` is a variable where the value is different for each thread. +# Each variable may have a default value, but when you modify the variable only +# the current thread will ever see that change. +# +# This is similar to Ruby's built-in thread-local variables (`Thread#thread_variable_get`), +# but with these major advantages: +# * `ThreadLocalVar` has its own identity, it doesn't need a Symbol. +# * Each Ruby's built-in thread-local variable leaks some memory forever (it's a Symbol held forever on the thread), +# so it's only OK to create a small amount of them. +# `ThreadLocalVar` has no such issue and it is fine to create many of them. +# * Ruby's built-in thread-local variables leak forever the value set on each thread (unless set to nil explicitly). +# `ThreadLocalVar` automatically removes the mapping for each thread once the `ThreadLocalVar` instance is GC'd. +# +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. +# +# @example +# v = ThreadLocalVar.new(14) +# v.value #=> 14 +# v.value = 2 +# v.value #=> 2 +# @example +# v = ThreadLocalVar.new(14) +# +# t1 = Thread.new do +# v.value #=> 14 +# v.value = 1 +# v.value #=> 1 +# end +# +# t2 = Thread.new do +# v.value #=> 14 +# v.value = 2 +# v.value #=> 2 +# end +# +# v.value #=> 14 +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#43 +class Concurrent::ThreadLocalVar + # Creates a thread local variable. + # + # @param default [Object] the default value when otherwise unset + # @param default_block [Proc] Optional block that gets called to obtain the + # default value for each thread + # @return [ThreadLocalVar] a new instance of ThreadLocalVar + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#51 + def initialize(default = T.unsafe(nil), &default_block); end + + # Bind the given value to thread local storage during + # execution of the given block. + # + # @param value [Object] the value to bind + # @return [Object] the value + # @yield the operation to be performed with the bound variable + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#88 + def bind(value); end + + # Returns the value in the current thread's copy of this thread-local variable. + # + # @return [Object] the current value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#70 + def value; end + + # Sets the current thread's copy of this thread-local variable to the specified value. + # + # @param value [Object] the value to set + # @return [Object] the new value + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#78 + def value=(value); end + + protected + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#103 + def default; end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb#44 +Concurrent::ThreadLocalVar::LOCALS = T.let(T.unsafe(nil), Concurrent::ThreadLocals) + +# An array-backed storage of indexed variables per thread. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#141 +class Concurrent::ThreadLocals < ::Concurrent::AbstractLocals + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#142 + def locals; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/atomic/locals.rb#146 + def locals!; end +end + +# An abstraction composed of one or more threads and a task queue. Tasks +# (blocks or `proc` objects) are submitted to the pool and added to the queue. +# The threads in the pool remove the tasks and execute them in the order +# they were received. +# +# A `ThreadPoolExecutor` will automatically adjust the pool size according +# to the bounds set by `min-threads` and `max-threads`. When a new task is +# submitted and fewer than `min-threads` threads are running, a new thread +# is created to handle the request, even if other worker threads are idle. +# If there are more than `min-threads` but less than `max-threads` threads +# running, a new thread will be created only if the queue is full. +# +# Threads that are idle for too long will be garbage collected, down to the +# configured minimum options. Should a thread crash it, too, will be garbage collected. +# +# `ThreadPoolExecutor` is based on the Java class of the same name. From +# the official Java documentation; +# +# > Thread pools address two different problems: they usually provide +# > improved performance when executing large numbers of asynchronous tasks, +# > due to reduced per-task invocation overhead, and they provide a means +# > of bounding and managing the resources, including threads, consumed +# > when executing a collection of tasks. Each ThreadPoolExecutor also +# > maintains some basic statistics, such as the number of completed tasks. +# > +# > To be useful across a wide range of contexts, this class provides many +# > adjustable parameters and extensibility hooks. However, programmers are +# > urged to use the more convenient Executors factory methods +# > [CachedThreadPool] (unbounded thread pool, with automatic thread reclamation), +# > [FixedThreadPool] (fixed size thread pool) and [SingleThreadExecutor] (single +# > background thread), that preconfigure settings for the most common usage +# > scenarios. +# +# **Thread Pool Options** +# +# Thread pools support several configuration options: +# +# * `idletime`: The number of seconds that a thread may be idle before being reclaimed. +# * `name`: The name of the executor (optional). Printed in the executor's `#to_s` output and +# a `-worker-` name is given to its threads if supported by used Ruby +# implementation. `` is uniq for each thread. +# * `max_queue`: The maximum number of tasks that may be waiting in the work queue at +# any one time. When the queue size reaches `max_queue` and no new threads can be created, +# subsequent tasks will be rejected in accordance with the configured `fallback_policy`. +# * `auto_terminate`: When true (default), the threads started will be marked as daemon. +# * `fallback_policy`: The policy defining how rejected tasks are handled. +# +# Three fallback policies are supported: +# +# * `:abort`: Raise a `RejectedExecutionError` exception and discard the task. +# * `:discard`: Discard the task and return false. +# * `:caller_runs`: Execute the task on the calling thread. +# +# **Shutting Down Thread Pools** +# +# Killing a thread pool while tasks are still being processed, either by calling +# the `#kill` method or at application exit, will have unpredictable results. There +# is no way for the thread pool to know what resources are being used by the +# in-progress tasks. When those tasks are killed the impact on those resources +# cannot be predicted. The *best* practice is to explicitly shutdown all thread +# pools using the provided methods: +# +# * Call `#shutdown` to initiate an orderly termination of all in-progress tasks +# * Call `#wait_for_termination` with an appropriate timeout interval an allow +# the orderly shutdown to complete +# * Call `#kill` *only when* the thread pool fails to shutdown in the allotted time +# +# On some runtime platforms (most notably the JVM) the application will not +# exit until all thread pools have been shutdown. To prevent applications from +# "hanging" on exit, all threads can be marked as daemon according to the +# `:auto_terminate` option. +# +# ```ruby +# pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon +# pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon +# ``` +# +# @note Failure to properly shutdown a thread pool can lead to unpredictable results. +# Please read *Shutting Down Thread Pools* for more information. +# @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools +# @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class +# @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface +# @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean- +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb#56 +class Concurrent::ThreadPoolExecutor < ::Concurrent::RubyThreadPoolExecutor; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb#10 +Concurrent::ThreadPoolExecutorImplementation = Concurrent::RubyThreadPoolExecutor + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#4 +module Concurrent::ThreadSafe; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#7 +module Concurrent::ThreadSafe::Util + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#16 + def make_synchronized_on_cruby(klass); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb#41 + def make_synchronized_on_truffleruby(klass); end + end +end + +# TODO (pitr-ch 15-Oct-2016): migrate to Utility::ProcessorCounter +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#13 +Concurrent::ThreadSafe::Util::CPU_COUNT = T.let(T.unsafe(nil), Integer) + +# TODO (pitr-ch 15-Oct-2016): migrate to Utility::NativeInteger +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#10 +Concurrent::ThreadSafe::Util::FIXNUM_BIT_SIZE = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/thread_safe/util.rb#11 +Concurrent::ThreadSafe::Util::MAX_INT = T.let(T.unsafe(nil), Integer) + +# Raised when an operation times out. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/errors.rb#55 +class Concurrent::TimeoutError < ::Concurrent::Error; end + +# Executes a collection of tasks, each after a given delay. A master task +# monitors the set and schedules each task for execution at the appropriate +# time. Tasks are run on the global thread pool or on the supplied executor. +# Each task is represented as a `ScheduledTask`. +# +# @see Concurrent::ScheduledTask +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#19 +class Concurrent::TimerSet < ::Concurrent::RubyExecutorService + # Create a new set of timed tasks. + # + # @option opts + # @param opts [Hash] the options used to specify the executor on which to perform actions + # @return [TimerSet] a new instance of TimerSet + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#30 + def initialize(opts = T.unsafe(nil)); end + + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#62 + def kill; end + + # Post a task to be execute run after a given delay (in seconds). If the + # delay is less than 1/100th of a second the task will be immediately post + # to the executor. + # + # @param delay [Float] the number of seconds to wait for before executing the task. + # @param args [Array] the arguments passed to the task on execution. + # @raise [ArgumentError] if the intended execution time is not in the future. + # @raise [ArgumentError] if no block is given. + # @return [Concurrent::ScheduledTask, false] IVar representing the task if the post + # is successful; false after shutdown. + # @yield the task to be performed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#48 + def post(delay, *args, &task); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#166 + def <<(task); end + + # Initialize the object. + # + # @param opts [Hash] the options to create the object with. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#74 + def ns_initialize(opts); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#94 + def ns_post_task(task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#129 + def ns_reset_if_forked; end + + # `ExecutorService` callback called during shutdown. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#122 + def ns_shutdown_execution; end + + # Post the task to the internal queue. + # + # @note This is intended as a callback method from ScheduledTask + # only. It is not intended to be used directly. Post a task + # by using the `SchedulesTask#execute` method. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#89 + def post_task(task); end + + # Run a loop and execute tasks in the scheduled order and at the approximate + # scheduled time. If no tasks remain the thread will exit gracefully so that + # garbage collection can occur. If there are no ready tasks it will sleep + # for up to 60 seconds waiting for the next scheduled task. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#143 + def process_tasks; end + + # Remove the given task from the queue. + # + # @note This is intended as a callback method from `ScheduledTask` + # only. It is not intended to be used directly. Cancel a task + # by using the `ScheduledTask#cancel` method. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/timer_set.rb#115 + def remove_task(task); end +end + +# A very common concurrency pattern is to run a thread that performs a task at +# regular intervals. The thread that performs the task sleeps for the given +# interval then wakes up and performs the task. Lather, rinse, repeat... This +# pattern causes two problems. First, it is difficult to test the business +# logic of the task because the task itself is tightly coupled with the +# concurrency logic. Second, an exception raised while performing the task can +# cause the entire thread to abend. In a long-running application where the +# task thread is intended to run for days/weeks/years a crashed task thread +# can pose a significant problem. `TimerTask` alleviates both problems. +# +# When a `TimerTask` is launched it starts a thread for monitoring the +# execution interval. The `TimerTask` thread does not perform the task, +# however. Instead, the TimerTask launches the task on a separate thread. +# Should the task experience an unrecoverable crash only the task thread will +# crash. This makes the `TimerTask` very fault tolerant. Additionally, the +# `TimerTask` thread can respond to the success or failure of the task, +# performing logging or ancillary operations. +# +# One other advantage of `TimerTask` is that it forces the business logic to +# be completely decoupled from the concurrency logic. The business logic can +# be tested separately then passed to the `TimerTask` for scheduling and +# running. +# +# A `TimerTask` supports two different types of interval calculations. +# A fixed delay will always wait the same amount of time between the +# completion of one task and the start of the next. A fixed rate will +# attempt to maintain a constant rate of execution regardless of the +# duration of the task. For example, if a fixed rate task is scheduled +# to run every 60 seconds but the task itself takes 10 seconds to +# complete, the next task will be scheduled to run 50 seconds after +# the start of the previous task. If the task takes 70 seconds to +# complete, the next task will be start immediately after the previous +# task completes. Tasks will not be executed concurrently. +# +# In some cases it may be necessary for a `TimerTask` to affect its own +# execution cycle. To facilitate this, a reference to the TimerTask instance +# is passed as an argument to the provided block every time the task is +# executed. +# +# The `TimerTask` class includes the `Dereferenceable` mixin module so the +# result of the last execution is always available via the `#value` method. +# Dereferencing options can be passed to the `TimerTask` during construction or +# at any later time using the `#set_deref_options` method. +# +# `TimerTask` supports notification through the Ruby standard library +# {http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html +# Observable} module. On execution the `TimerTask` will notify the observers +# with three arguments: time of execution, the result of the block (or nil on +# failure), and any raised exceptions (or nil on success). +# +# @example Basic usage +# task = Concurrent::TimerTask.new{ puts 'Boom!' } +# task.execute +# +# task.execution_interval #=> 60 (default) +# +# # wait 60 seconds... +# #=> 'Boom!' +# +# task.shutdown #=> true +# @example Configuring `:execution_interval` +# task = Concurrent::TimerTask.new(execution_interval: 5) do +# puts 'Boom!' +# end +# +# task.execution_interval #=> 5 +# @example Immediate execution with `:run_now` +# task = Concurrent::TimerTask.new(run_now: true){ puts 'Boom!' } +# task.execute +# +# #=> 'Boom!' +# @example Configuring `:interval_type` with either :fixed_delay or :fixed_rate, default is :fixed_delay +# task = Concurrent::TimerTask.new(execution_interval: 5, interval_type: :fixed_rate) do +# puts 'Boom!' +# end +# task.interval_type #=> :fixed_rate +# @example Last `#value` and `Dereferenceable` mixin +# task = Concurrent::TimerTask.new( +# dup_on_deref: true, +# execution_interval: 5 +# ){ Time.now } +# +# task.execute +# Time.now #=> 2013-11-07 18:06:50 -0500 +# sleep(10) +# task.value #=> 2013-11-07 18:06:55 -0500 +# @example Controlling execution from within the block +# timer_task = Concurrent::TimerTask.new(execution_interval: 1) do |task| +# task.execution_interval.to_i.times{ print 'Boom! ' } +# print "\n" +# task.execution_interval += 1 +# if task.execution_interval > 5 +# puts 'Stopping...' +# task.shutdown +# end +# end +# +# timer_task.execute +# #=> Boom! +# #=> Boom! Boom! +# #=> Boom! Boom! Boom! +# #=> Boom! Boom! Boom! Boom! +# #=> Boom! Boom! Boom! Boom! Boom! +# #=> Stopping... +# @example Observation +# class TaskObserver +# def update(time, result, ex) +# if result +# print "(#{time}) Execution successfully returned #{result}\n" +# else +# print "(#{time}) Execution failed with error #{ex}\n" +# end +# end +# end +# +# task = Concurrent::TimerTask.new(execution_interval: 1){ 42 } +# task.add_observer(TaskObserver.new) +# task.execute +# sleep 4 +# +# #=> (2013-10-13 19:08:58 -0400) Execution successfully returned 42 +# #=> (2013-10-13 19:08:59 -0400) Execution successfully returned 42 +# #=> (2013-10-13 19:09:00 -0400) Execution successfully returned 42 +# task.shutdown +# +# task = Concurrent::TimerTask.new(execution_interval: 1){ sleep } +# task.add_observer(TaskObserver.new) +# task.execute +# +# #=> (2013-10-13 19:07:25 -0400) Execution timed out +# #=> (2013-10-13 19:07:27 -0400) Execution timed out +# #=> (2013-10-13 19:07:29 -0400) Execution timed out +# task.shutdown +# +# task = Concurrent::TimerTask.new(execution_interval: 1){ raise StandardError } +# task.add_observer(TaskObserver.new) +# task.execute +# +# #=> (2013-10-13 19:09:37 -0400) Execution failed with error StandardError +# #=> (2013-10-13 19:09:38 -0400) Execution failed with error StandardError +# #=> (2013-10-13 19:09:39 -0400) Execution failed with error StandardError +# task.shutdown +# @see http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html +# @see http://docs.oracle.com/javase/7/docs/api/java/util/TimerTask.html +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#165 +class Concurrent::TimerTask < ::Concurrent::RubyExecutorService + include ::Concurrent::Concern::Dereferenceable + include ::Concurrent::Concern::Observable + + # Create a new TimerTask with the given task and configuration. + # + # @option opts + # @option opts + # @option opts + # @param opts [Hash] the options defining task execution. + # @raise ArgumentError when no block is given. + # @return [TimerTask] the new `TimerTask` + # @yield to the block after :execution_interval seconds have passed since + # the last yield + # @yieldparam task a reference to the `TimerTask` instance so that the + # block can control its own lifecycle. Necessary since `self` will + # refer to the execution context of the block rather than the running + # `TimerTask`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#209 + def initialize(opts = T.unsafe(nil), &task); end + + # Execute a previously created `TimerTask`. + # + # @example Instance and execute in separate steps + # task = Concurrent::TimerTask.new(execution_interval: 10){ print "Hello World\n" } + # task.running? #=> false + # task.execute + # task.running? #=> true + # @example Instance and execute in one line + # task = Concurrent::TimerTask.new(execution_interval: 10){ print "Hello World\n" }.execute + # task.running? #=> true + # @return [TimerTask] a reference to `self` + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#235 + def execute; end + + # @return [Fixnum] Number of seconds after the task completes before the + # task is performed again. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#259 + def execution_interval; end + + # @return [Fixnum] Number of seconds after the task completes before the + # task is performed again. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#266 + def execution_interval=(value); end + + # @return [Symbol] method to calculate the interval between executions + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#276 + def interval_type; end + + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#218 + def running?; end + + # @return [Fixnum] Number of seconds the task can run before it is + # considered to have failed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#281 + def timeout_interval; end + + # @return [Fixnum] Number of seconds the task can run before it is + # considered to have failed. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#288 + def timeout_interval=(value); end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/executor_service.rb#166 + def <<(task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#352 + def calculate_next_interval(start_time); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#336 + def execute_task(completion); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#296 + def ns_initialize(opts, &task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#324 + def ns_kill_execution; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#318 + def ns_shutdown_execution; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb#17 + def post(*args, &task); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#330 + def schedule_next_task(interval = T.unsafe(nil)); end + + class << self + # Create and execute a new `TimerTask`. + # + # @example + # task = Concurrent::TimerTask.execute(execution_interval: 10){ print "Hello World\n" } + # task.running? #=> true + # @option opts + # @option opts + # @option opts + # @param opts [Hash] the options defining task execution. + # @raise ArgumentError when no block is given. + # @return [TimerTask] the new `TimerTask` + # @yield to the block after :execution_interval seconds have passed since + # the last yield + # @yieldparam task a reference to the `TimerTask` instance so that the + # block can control its own lifecycle. Necessary since `self` will + # refer to the execution context of the block rather than the running + # `TimerTask`. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#252 + def execute(opts = T.unsafe(nil), &task); end + end +end + +# Default `:interval_type` +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#181 +Concurrent::TimerTask::DEFAULT_INTERVAL_TYPE = T.let(T.unsafe(nil), Symbol) + +# Default `:execution_interval` in seconds. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#170 +Concurrent::TimerTask::EXECUTION_INTERVAL = T.let(T.unsafe(nil), Integer) + +# Maintain the interval between the end of one execution and the start of the next execution. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#173 +Concurrent::TimerTask::FIXED_DELAY = T.let(T.unsafe(nil), Symbol) + +# Maintain the interval between the start of one execution and the start of the next. +# If execution time exceeds the interval, the next execution will start immediately +# after the previous execution finishes. Executions will not run concurrently. +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/timer_task.rb#178 +Concurrent::TimerTask::FIXED_RATE = T.let(T.unsafe(nil), Symbol) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#153 +class Concurrent::Transaction + # @return [Transaction] a new instance of Transaction + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#162 + def initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#192 + def abort; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#196 + def commit; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#177 + def open(tvar); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#166 + def read(tvar); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#206 + def unlock; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#171 + def write(tvar, value); end + + class << self + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#212 + def current; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#216 + def current=(transaction); end + end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#155 +Concurrent::Transaction::ABORTED = T.let(T.unsafe(nil), Object) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#159 +class Concurrent::Transaction::AbortError < ::StandardError; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#160 +class Concurrent::Transaction::LeaveError < ::StandardError; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tvar.rb#157 +class Concurrent::Transaction::OpenEntry < ::Struct + # Returns the value of attribute modified + # + # @return [Object] the current value of modified + def modified; end + + # Sets the attribute modified + # + # @param value [Object] the value to set the attribute modified to. + # @return [Object] the newly set value + def modified=(_); end + + # Returns the value of attribute value + # + # @return [Object] the current value of value + def value; end + + # Sets the attribute value + # + # @param value [Object] the value to set the attribute value to. + # @return [Object] the newly set value + def value=(_); end + + class << self + def [](*_arg0); end + def inspect; end + def keyword_init?; end + def members; end + def new(*_arg0); end + end +end + +# A fixed size array with volatile (synchronized, thread safe) getters/setters. +# Mixes in Ruby's `Enumerable` module for enhanced search, sort, and traversal. +# +# @example +# tuple = Concurrent::Tuple.new(16) +# +# tuple.set(0, :foo) #=> :foo | volatile write +# tuple.get(0) #=> :foo | volatile read +# tuple.compare_and_set(0, :foo, :bar) #=> true | strong CAS +# tuple.cas(0, :foo, :baz) #=> false | strong CAS +# tuple.get(0) #=> :bar | volatile read +# @see https://en.wikipedia.org/wiki/Tuple Tuple entry at Wikipedia +# @see http://www.erlang.org/doc/reference_manual/data_types.html#id70396 Erlang Tuple +# @see http://ruby-doc.org/core-2.2.2/Enumerable.html Enumerable +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#20 +class Concurrent::Tuple + include ::Enumerable + + # Create a new tuple of the given size. + # + # @param size [Integer] the number of elements in the tuple + # @return [Tuple] a new instance of Tuple + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#29 + def initialize(size); end + + # Set the value at the given index to the new value if and only if the current + # value matches the given old value. + # + # @param i [Integer] the index for the element to set + # @param old_value [Object] the value to compare against the current value + # @param new_value [Object] the value to set at the given index + # @return [Boolean] true if the value at the given element was set else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#69 + def cas(i, old_value, new_value); end + + # Set the value at the given index to the new value if and only if the current + # value matches the given old value. + # + # @param i [Integer] the index for the element to set + # @param old_value [Object] the value to compare against the current value + # @param new_value [Object] the value to set at the given index + # @return [Boolean] true if the value at the given element was set else false + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#69 + def compare_and_set(i, old_value, new_value); end + + # Calls the given block once for each element in self, passing that element as a parameter. + # + # @yieldparam ref [Object] the `Concurrent::AtomicReference` object at the current index + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#78 + def each; end + + # Get the value of the element at the given index. + # + # @param i [Integer] the index from which to retrieve the value + # @return [Object] the value at the given index or nil if the index is out of bounds + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#43 + def get(i); end + + # Set the element at the given index to the given value + # + # @param i [Integer] the index for the element to set + # @param value [Object] the value to set at the given index + # @return [Object] the new value of the element at the given index or nil if the index is out of bounds + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#55 + def set(i, value); end + + # The (fixed) size of the tuple. + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#24 + def size; end + + # Get the value of the element at the given index. + # + # @param i [Integer] the index from which to retrieve the value + # @return [Object] the value at the given index or nil if the index is out of bounds + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#43 + def volatile_get(i); end + + # Set the element at the given index to the given value + # + # @param i [Integer] the index for the element to set + # @param value [Object] the value to set at the given index + # @return [Object] the new value of the element at the given index or nil if the index is out of bounds + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/tuple.rb#55 + def volatile_set(i, value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#3 +module Concurrent::Utility; end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#6 +module Concurrent::Utility::EngineDetector + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#7 + def on_cruby?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#11 + def on_jruby?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#27 + def on_linux?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#23 + def on_osx?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#15 + def on_truffleruby?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#19 + def on_windows?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/engine.rb#31 + def ruby_version(version = T.unsafe(nil), comparison, major, minor, patch); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#9 +module Concurrent::Utility::NativeExtensionLoader + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#11 + def allow_c_extensions?; end + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#15 + def c_extensions_loaded?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#19 + def load_native_extensions; end + + private + + # @return [Boolean] + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#50 + def java_extensions_loaded?; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#38 + def load_error_path(error); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#46 + def set_c_extensions_loaded; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#54 + def set_java_extensions_loaded; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb#58 + def try_load_c_extension(path); end +end + +# @private +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#5 +module Concurrent::Utility::NativeInteger + extend ::Concurrent::Utility::NativeInteger + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#24 + def ensure_integer(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#31 + def ensure_integer_and_bounds(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#17 + def ensure_lower_bound(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#37 + def ensure_positive(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#44 + def ensure_positive_and_no_zero(value); end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#10 + def ensure_upper_bound(value); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#8 +Concurrent::Utility::NativeInteger::MAX_VALUE = T.let(T.unsafe(nil), Integer) + +# http://stackoverflow.com/questions/535721/ruby-max-integer +# +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/native_integer.rb#7 +Concurrent::Utility::NativeInteger::MIN_VALUE = T.let(T.unsafe(nil), Integer) + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#10 +class Concurrent::Utility::ProcessorCounter + # @return [ProcessorCounter] a new instance of ProcessorCounter + # + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#11 + def initialize; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#26 + def available_processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#41 + def cpu_quota; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#45 + def cpu_shares; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#22 + def physical_processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#18 + def processor_count; end + + private + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#104 + def compute_cpu_quota; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#124 + def compute_cpu_shares; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#59 + def compute_physical_processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#51 + def compute_processor_count; end + + # source://concurrent-ruby//lib/concurrent-ruby/concurrent/utility/processor_counter.rb#99 + def run(command); end +end + +# source://concurrent-ruby//lib/concurrent-ruby/concurrent/version.rb#2 +Concurrent::VERSION = T.let(T.unsafe(nil), String) diff --git a/Library/Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi b/Library/Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi new file mode 100644 index 0000000000000..f72a0eed60f48 --- /dev/null +++ b/Library/Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi @@ -0,0 +1,103 @@ +# typed: true + +# DO NOT EDIT MANUALLY +# This is an autogenerated file for types exported from the `whirly` gem. +# Please instead update this file by running `bin/tapioca gem whirly`. + + +# source://whirly//lib/whirly/version.rb#3 +module Whirly + class << self + # save options and preprocess, set defaults if value is still unknown + # + # source://whirly//lib/whirly.rb#114 + def configure(**options); end + + # frames can be generated from enumerables or procs + # + # source://whirly//lib/whirly.rb#85 + def configure_frames(spinner); end + + # set spinner directly or lookup + # + # source://whirly//lib/whirly.rb#55 + def configure_spinner(spinner_option); end + + # @return [Boolean] + # + # source://whirly//lib/whirly.rb#49 + def configured?; end + + # @return [Boolean] + # + # source://whirly//lib/whirly.rb#45 + def enabled?; end + + # source://whirly//lib/whirly.rb#240 + def initialize_color; end + + # source://whirly//lib/whirly.rb#249 + def next_color; end + + # Returns the value of attribute options. + # + # source://whirly//lib/whirly.rb#43 + def options; end + + # source://whirly//lib/whirly.rb#215 + def render(next_frame = T.unsafe(nil)); end + + # source://whirly//lib/whirly.rb#225 + def render_prefix; end + + # source://whirly//lib/whirly.rb#233 + def render_suffix; end + + # source://whirly//lib/whirly.rb#194 + def reset; end + + # source://whirly//lib/whirly.rb#132 + def start(**options); end + + # Returns the value of attribute status. + # + # source://whirly//lib/whirly.rb#42 + def status; end + + # Sets the attribute status + # + # @param value the value to set the attribute status to. + # + # source://whirly//lib/whirly.rb#42 + def status=(_arg0); end + + # source://whirly//lib/whirly.rb#180 + def stop(stop_frame = T.unsafe(nil)); end + + # - - - + # + # source://whirly//lib/whirly.rb#203 + def unrender; end + end +end + +# source://whirly//lib/whirly.rb#14 +Whirly::CLI_COMMANDS = T.let(T.unsafe(nil), Hash) + +# source://whirly//lib/whirly.rb#19 +Whirly::DEFAULT_OPTIONS = T.let(T.unsafe(nil), Hash) + +# source://whirly//lib/whirly.rb#35 +Whirly::SOFT_DEFAULT_OPTIONS = T.let(T.unsafe(nil), Hash) + +# source://whirly//lib/whirly/spinners.rb#2 +module Whirly::Spinners; end + +# source://whirly//lib/whirly/spinners/cli.rb#5 +Whirly::Spinners::CLI = T.let(T.unsafe(nil), Hash) + +# source://whirly//lib/whirly/spinners/whirly.rb#5 +Whirly::Spinners::WHIRLY = T.let(T.unsafe(nil), Hash) + +# source://whirly//lib/whirly/version.rb#4 +Whirly::VERSION = T.let(T.unsafe(nil), String) diff --git a/Library/Homebrew/vendor/bundle/bundler/setup.rb b/Library/Homebrew/vendor/bundle/bundler/setup.rb index 6d51885d702a9..d1fc474ed35a8 100644 --- a/Library/Homebrew/vendor/bundle/bundler/setup.rb +++ b/Library/Homebrew/vendor/bundle/bundler/setup.rb @@ -43,6 +43,7 @@ def self.extension_api_version $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/coderay-1.1.3/lib") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/highline-3.0.1/lib") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/commander-5.0.0/lib") +$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/diff-lcs-1.5.1/lib") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/docile-1.4.1/lib") $:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/elftools-1.3.1/lib") diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/LICENSE.txt b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/LICENSE.txt new file mode 100644 index 0000000000000..1026f28d0be92 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) Jerry D'Antonio -- released under the MIT license. + +http://www.opensource.org/licenses/mit-license.php + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent-ruby.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent-ruby.rb new file mode 100644 index 0000000000000..e9a3dea4ab40d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent-ruby.rb @@ -0,0 +1,5 @@ +# This file is here so that there is a file with the same name as the gem that +# can be required by Bundler.require. Applications should normally +# require 'concurrent'. + +require_relative "concurrent" diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent.rb new file mode 100644 index 0000000000000..87de46f1b8a1b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent.rb @@ -0,0 +1,134 @@ +require 'concurrent/version' +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/configuration' + +require 'concurrent/atomics' +require 'concurrent/executors' +require 'concurrent/synchronization' + +require 'concurrent/atomic/atomic_markable_reference' +require 'concurrent/atomic/atomic_reference' +require 'concurrent/agent' +require 'concurrent/atom' +require 'concurrent/array' +require 'concurrent/hash' +require 'concurrent/set' +require 'concurrent/map' +require 'concurrent/tuple' +require 'concurrent/async' +require 'concurrent/dataflow' +require 'concurrent/delay' +require 'concurrent/exchanger' +require 'concurrent/future' +require 'concurrent/immutable_struct' +require 'concurrent/ivar' +require 'concurrent/maybe' +require 'concurrent/mutable_struct' +require 'concurrent/mvar' +require 'concurrent/promise' +require 'concurrent/scheduled_task' +require 'concurrent/settable_struct' +require 'concurrent/timer_task' +require 'concurrent/tvar' +require 'concurrent/promises' + +require 'concurrent/thread_safe/synchronized_delegator' +require 'concurrent/thread_safe/util' + +require 'concurrent/options' + +# @!macro internal_implementation_note +# +# @note **Private Implementation:** This abstraction is a private, internal +# implementation detail. It should never be used directly. + +# @!macro monotonic_clock_warning +# +# @note Time calculations on all platforms and languages are sensitive to +# changes to the system clock. To alleviate the potential problems +# associated with changing the system clock while an application is running, +# most modern operating systems provide a monotonic clock that operates +# independently of the system clock. A monotonic clock cannot be used to +# determine human-friendly clock times. A monotonic clock is used exclusively +# for calculating time intervals. Not all Ruby platforms provide access to an +# operating system monotonic clock. On these platforms a pure-Ruby monotonic +# clock will be used as a fallback. An operating system monotonic clock is both +# faster and more reliable than the pure-Ruby implementation. The pure-Ruby +# implementation should be fast and reliable enough for most non-realtime +# operations. At this time the common Ruby platforms that provide access to an +# operating system monotonic clock are MRI 2.1 and above and JRuby (all versions). +# +# @see http://linux.die.net/man/3/clock_gettime Linux clock_gettime(3) + +# @!macro copy_options +# +# ## Copy Options +# +# Object references in Ruby are mutable. This can lead to serious +# problems when the {#value} of an object is a mutable reference. Which +# is always the case unless the value is a `Fixnum`, `Symbol`, or similar +# "primitive" data type. Each instance can be configured with a few +# options that can help protect the program from potentially dangerous +# operations. Each of these options can be optionally set when the object +# instance is created: +# +# * `:dup_on_deref` When true the object will call the `#dup` method on +# the `value` object every time the `#value` method is called +# (default: false) +# * `:freeze_on_deref` When true the object will call the `#freeze` +# method on the `value` object every time the `#value` method is called +# (default: false) +# * `:copy_on_deref` When given a `Proc` object the `Proc` will be run +# every time the `#value` method is called. The `Proc` will be given +# the current `value` as its only argument and the result returned by +# the block will be the return value of the `#value` call. When `nil` +# this option will be ignored (default: nil) +# +# When multiple deref options are set the order of operations is strictly defined. +# The order of deref operations is: +# * `:copy_on_deref` +# * `:dup_on_deref` +# * `:freeze_on_deref` +# +# Because of this ordering there is no need to `#freeze` an object created by a +# provided `:copy_on_deref` block. Simply set `:freeze_on_deref` to `true`. +# Setting both `:dup_on_deref` to `true` and `:freeze_on_deref` to `true` is +# as close to the behavior of a "pure" functional language (like Erlang, Clojure, +# or Haskell) as we are likely to get in Ruby. + +# @!macro deref_options +# +# @option opts [Boolean] :dup_on_deref (false) Call `#dup` before +# returning the data from {#value} +# @option opts [Boolean] :freeze_on_deref (false) Call `#freeze` before +# returning the data from {#value} +# @option opts [Proc] :copy_on_deref (nil) When calling the {#value} +# method, call the given proc passing the internal value as the sole +# argument then return the new value returned from the proc. + +# @!macro executor_and_deref_options +# +# @param [Hash] opts the options used to define the behavior at update and deref +# and to specify the executor on which to perform actions +# @option opts [Executor] :executor when set use the given `Executor` instance. +# Three special values are also supported: `:io` returns the global pool for +# long, blocking (IO) tasks, `:fast` returns the global pool for short, fast +# operations, and `:immediate` returns the global `ImmediateExecutor` object. +# @!macro deref_options + +# @!macro warn.edge +# @api Edge +# @note **Edge Features** are under active development and may change frequently. +# +# - Deprecations are not added before incompatible changes. +# - Edge version: _major_ is always 0, _minor_ bump means incompatible change, +# _patch_ bump means compatible change. +# - Edge features may also lack tests and documentation. +# - Features developed in `concurrent-ruby-edge` are expected to move +# to `concurrent-ruby` when finalised. + + +# {include:file:README.md} +module Concurrent +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/agent.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/agent.rb new file mode 100644 index 0000000000000..2d32926ba14d0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/agent.rb @@ -0,0 +1,588 @@ +require 'concurrent/configuration' +require 'concurrent/atomic/atomic_reference' +require 'concurrent/atomic/count_down_latch' +require 'concurrent/atomic/thread_local_var' +require 'concurrent/collection/copy_on_write_observer_set' +require 'concurrent/concern/observable' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # `Agent` is inspired by Clojure's [agent](http://clojure.org/agents) + # function. An agent is a shared, mutable variable providing independent, + # uncoordinated, *asynchronous* change of individual values. Best used when + # the value will undergo frequent, complex updates. Suitable when the result + # of an update does not need to be known immediately. `Agent` is (mostly) + # functionally equivalent to Clojure's agent, except where the runtime + # prevents parity. + # + # Agents are reactive, not autonomous - there is no imperative message loop + # and no blocking receive. The state of an Agent should be itself immutable + # and the `#value` of an Agent is always immediately available for reading by + # any thread without any messages, i.e. observation does not require + # cooperation or coordination. + # + # Agent action dispatches are made using the various `#send` methods. These + # methods always return immediately. At some point later, in another thread, + # the following will happen: + # + # 1. The given `action` will be applied to the state of the Agent and the + # `args`, if any were supplied. + # 2. The return value of `action` will be passed to the validator lambda, + # if one has been set on the Agent. + # 3. If the validator succeeds or if no validator was given, the return value + # of the given `action` will become the new `#value` of the Agent. See + # `#initialize` for details. + # 4. If any observers were added to the Agent, they will be notified. See + # `#add_observer` for details. + # 5. If during the `action` execution any other dispatches are made (directly + # or indirectly), they will be held until after the `#value` of the Agent + # has been changed. + # + # If any exceptions are thrown by an action function, no nested dispatches + # will occur, and the exception will be cached in the Agent itself. When an + # Agent has errors cached, any subsequent interactions will immediately throw + # an exception, until the agent's errors are cleared. Agent errors can be + # examined with `#error` and the agent restarted with `#restart`. + # + # The actions of all Agents get interleaved amongst threads in a thread pool. + # At any point in time, at most one action for each Agent is being executed. + # Actions dispatched to an agent from another single agent or thread will + # occur in the order they were sent, potentially interleaved with actions + # dispatched to the same agent from other sources. The `#send` method should + # be used for actions that are CPU limited, while the `#send_off` method is + # appropriate for actions that may block on IO. + # + # Unlike in Clojure, `Agent` cannot participate in `Concurrent::TVar` transactions. + # + # ## Example + # + # ``` + # def next_fibonacci(set = nil) + # return [0, 1] if set.nil? + # set + [set[-2..-1].reduce{|sum,x| sum + x }] + # end + # + # # create an agent with an initial value + # agent = Concurrent::Agent.new(next_fibonacci) + # + # # send a few update requests + # 5.times do + # agent.send{|set| next_fibonacci(set) } + # end + # + # # wait for them to complete + # agent.await + # + # # get the current value + # agent.value #=> [0, 1, 1, 2, 3, 5, 8] + # ``` + # + # ## Observation + # + # Agents support observers through the {Concurrent::Observable} mixin module. + # Notification of observers occurs every time an action dispatch returns and + # the new value is successfully validated. Observation will *not* occur if the + # action raises an exception, if validation fails, or when a {#restart} occurs. + # + # When notified the observer will receive three arguments: `time`, `old_value`, + # and `new_value`. The `time` argument is the time at which the value change + # occurred. The `old_value` is the value of the Agent when the action began + # processing. The `new_value` is the value to which the Agent was set when the + # action completed. Note that `old_value` and `new_value` may be the same. + # This is not an error. It simply means that the action returned the same + # value. + # + # ## Nested Actions + # + # It is possible for an Agent action to post further actions back to itself. + # The nested actions will be enqueued normally then processed *after* the + # outer action completes, in the order they were sent, possibly interleaved + # with action dispatches from other threads. Nested actions never deadlock + # with one another and a failure in a nested action will never affect the + # outer action. + # + # Nested actions can be called using the Agent reference from the enclosing + # scope or by passing the reference in as a "send" argument. Nested actions + # cannot be post using `self` from within the action block/proc/lambda; `self` + # in this context will not reference the Agent. The preferred method for + # dispatching nested actions is to pass the Agent as an argument. This allows + # Ruby to more effectively manage the closing scope. + # + # Prefer this: + # + # ``` + # agent = Concurrent::Agent.new(0) + # agent.send(agent) do |value, this| + # this.send {|v| v + 42 } + # 3.14 + # end + # agent.value #=> 45.14 + # ``` + # + # Over this: + # + # ``` + # agent = Concurrent::Agent.new(0) + # agent.send do |value| + # agent.send {|v| v + 42 } + # 3.14 + # end + # ``` + # + # @!macro agent_await_warning + # + # **NOTE** Never, *under any circumstances*, call any of the "await" methods + # ({#await}, {#await_for}, {#await_for!}, and {#wait}) from within an action + # block/proc/lambda. The call will block the Agent and will always fail. + # Calling either {#await} or {#wait} (with a timeout of `nil`) will + # hopelessly deadlock the Agent with no possibility of recovery. + # + # @!macro thread_safe_variable_comparison + # + # @see http://clojure.org/Agents Clojure Agents + # @see http://clojure.org/state Values and Change - Clojure's approach to Identity and State + class Agent < Synchronization::LockableObject + include Concern::Observable + + ERROR_MODES = [:continue, :fail].freeze + private_constant :ERROR_MODES + + AWAIT_FLAG = ::Object.new + private_constant :AWAIT_FLAG + + AWAIT_ACTION = ->(value, latch) { latch.count_down; AWAIT_FLAG } + private_constant :AWAIT_ACTION + + DEFAULT_ERROR_HANDLER = ->(agent, error) { nil } + private_constant :DEFAULT_ERROR_HANDLER + + DEFAULT_VALIDATOR = ->(value) { true } + private_constant :DEFAULT_VALIDATOR + + Job = Struct.new(:action, :args, :executor, :caller) + private_constant :Job + + # Raised during action processing or any other time in an Agent's lifecycle. + class Error < StandardError + def initialize(message = nil) + message ||= 'agent must be restarted before jobs can post' + super(message) + end + end + + # Raised when a new value obtained during action processing or at `#restart` + # fails validation. + class ValidationError < Error + def initialize(message = nil) + message ||= 'invalid value' + super(message) + end + end + + # The error mode this Agent is operating in. See {#initialize} for details. + attr_reader :error_mode + + # Create a new `Agent` with the given initial value and options. + # + # The `:validator` option must be `nil` or a side-effect free proc/lambda + # which takes one argument. On any intended value change the validator, if + # provided, will be called. If the new value is invalid the validator should + # return `false` or raise an error. + # + # The `:error_handler` option must be `nil` or a proc/lambda which takes two + # arguments. When an action raises an error or validation fails, either by + # returning false or raising an error, the error handler will be called. The + # arguments to the error handler will be a reference to the agent itself and + # the error object which was raised. + # + # The `:error_mode` may be either `:continue` (the default if an error + # handler is given) or `:fail` (the default if error handler nil or not + # given). + # + # If an action being run by the agent throws an error or doesn't pass + # validation the error handler, if present, will be called. After the + # handler executes if the error mode is `:continue` the Agent will continue + # as if neither the action that caused the error nor the error itself ever + # happened. + # + # If the mode is `:fail` the Agent will become {#failed?} and will stop + # accepting new action dispatches. Any previously queued actions will be + # held until {#restart} is called. The {#value} method will still work, + # returning the value of the Agent before the error. + # + # @param [Object] initial the initial value + # @param [Hash] opts the configuration options + # + # @option opts [Symbol] :error_mode either `:continue` or `:fail` + # @option opts [nil, Proc] :error_handler the (optional) error handler + # @option opts [nil, Proc] :validator the (optional) validation procedure + def initialize(initial, opts = {}) + super() + synchronize { ns_initialize(initial, opts) } + end + + # The current value (state) of the Agent, irrespective of any pending or + # in-progress actions. The value is always available and is non-blocking. + # + # @return [Object] the current value + def value + @current.value # TODO (pitr 12-Sep-2015): broken unsafe read? + end + + alias_method :deref, :value + + # When {#failed?} and {#error_mode} is `:fail`, returns the error object + # which caused the failure, else `nil`. When {#error_mode} is `:continue` + # will *always* return `nil`. + # + # @return [nil, Error] the error which caused the failure when {#failed?} + def error + @error.value + end + + alias_method :reason, :error + + # @!macro agent_send + # + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Action dispatches are only allowed when the Agent + # is not {#failed?}. + # + # The action must be a block/proc/lambda which takes 1 or more arguments. + # The first argument is the current {#value} of the Agent. Any arguments + # passed to the send method via the `args` parameter will be passed to the + # action as the remaining arguments. The action must return the new value + # of the Agent. + # + # * {#send} and {#send!} should be used for actions that are CPU limited + # * {#send_off}, {#send_off!}, and {#<<} are appropriate for actions that + # may block on IO + # * {#send_via} and {#send_via!} are used when a specific executor is to + # be used for the action + # + # @param [Array] args zero or more arguments to be passed to + # the action + # @param [Proc] action the action dispatch to be enqueued + # + # @yield [agent, value, *args] process the old value and return the new + # @yieldparam [Object] value the current {#value} of the Agent + # @yieldparam [Array] args zero or more arguments to pass to the + # action + # @yieldreturn [Object] the new value of the Agent + # + # @!macro send_return + # @return [Boolean] true if the action is successfully enqueued, false if + # the Agent is {#failed?} + def send(*args, &action) + enqueue_action_job(action, args, Concurrent.global_fast_executor) + end + + # @!macro agent_send + # + # @!macro send_bang_return_and_raise + # @return [Boolean] true if the action is successfully enqueued + # @raise [Concurrent::Agent::Error] if the Agent is {#failed?} + def send!(*args, &action) + raise Error.new unless send(*args, &action) + true + end + + # @!macro agent_send + # @!macro send_return + def send_off(*args, &action) + enqueue_action_job(action, args, Concurrent.global_io_executor) + end + + alias_method :post, :send_off + + # @!macro agent_send + # @!macro send_bang_return_and_raise + def send_off!(*args, &action) + raise Error.new unless send_off(*args, &action) + true + end + + # @!macro agent_send + # @!macro send_return + # @param [Concurrent::ExecutorService] executor the executor on which the + # action is to be dispatched + def send_via(executor, *args, &action) + enqueue_action_job(action, args, executor) + end + + # @!macro agent_send + # @!macro send_bang_return_and_raise + # @param [Concurrent::ExecutorService] executor the executor on which the + # action is to be dispatched + def send_via!(executor, *args, &action) + raise Error.new unless send_via(executor, *args, &action) + true + end + + # Dispatches an action to the Agent and returns immediately. Subsequently, + # in a thread from a thread pool, the {#value} will be set to the return + # value of the action. Appropriate for actions that may block on IO. + # + # @param [Proc] action the action dispatch to be enqueued + # @return [Concurrent::Agent] self + # @see #send_off + def <<(action) + send_off(&action) + self + end + + # Blocks the current thread (indefinitely!) until all actions dispatched + # thus far, from this thread or nested by the Agent, have occurred. Will + # block when {#failed?}. Will never return if a failed Agent is {#restart} + # with `:clear_actions` true. + # + # Returns a reference to `self` to support method chaining: + # + # ``` + # current_value = agent.await.value + # ``` + # + # @return [Boolean] self + # + # @!macro agent_await_warning + def await + wait(nil) + self + end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. + # + # @param [Float] timeout the maximum number of seconds to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # @!macro agent_await_warning + def await_for(timeout) + wait(timeout.to_f) + end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. + # + # @param [Float] timeout the maximum number of seconds to wait + # @return [Boolean] true if all actions complete before timeout + # + # @raise [Concurrent::TimeoutError] when timout is reached + # + # @!macro agent_await_warning + def await_for!(timeout) + raise Concurrent::TimeoutError unless wait(timeout.to_f) + true + end + + # Blocks the current thread until all actions dispatched thus far, from this + # thread or nested by the Agent, have occurred, or the timeout (in seconds) + # has elapsed. Will block indefinitely when timeout is nil or not given. + # + # Provided mainly for consistency with other classes in this library. Prefer + # the various `await` methods instead. + # + # @param [Float] timeout the maximum number of seconds to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # @!macro agent_await_warning + def wait(timeout = nil) + latch = Concurrent::CountDownLatch.new(1) + enqueue_await_job(latch) + latch.wait(timeout) + end + + # Is the Agent in a failed state? + # + # @see #restart + def failed? + !@error.value.nil? + end + + alias_method :stopped?, :failed? + + # When an Agent is {#failed?}, changes the Agent {#value} to `new_value` + # then un-fails the Agent so that action dispatches are allowed again. If + # the `:clear_actions` option is give and true, any actions queued on the + # Agent that were being held while it was failed will be discarded, + # otherwise those held actions will proceed. The `new_value` must pass the + # validator if any, or `restart` will raise an exception and the Agent will + # remain failed with its old {#value} and {#error}. Observers, if any, will + # not be notified of the new state. + # + # @param [Object] new_value the new value for the Agent once restarted + # @param [Hash] opts the configuration options + # @option opts [Symbol] :clear_actions true if all enqueued but unprocessed + # actions should be discarded on restart, else false (default: false) + # @return [Boolean] true + # + # @raise [Concurrent:AgentError] when not failed + def restart(new_value, opts = {}) + clear_actions = opts.fetch(:clear_actions, false) + synchronize do + raise Error.new('agent is not failed') unless failed? + raise ValidationError unless ns_validate(new_value) + @current.value = new_value + @error.value = nil + @queue.clear if clear_actions + ns_post_next_job unless @queue.empty? + end + true + end + + class << self + + # Blocks the current thread (indefinitely!) until all actions dispatched + # thus far to all the given Agents, from this thread or nested by the + # given Agents, have occurred. Will block when any of the agents are + # failed. Will never return if a failed Agent is restart with + # `:clear_actions` true. + # + # @param [Array] agents the Agents on which to wait + # @return [Boolean] true + # + # @!macro agent_await_warning + def await(*agents) + agents.each { |agent| agent.await } + true + end + + # Blocks the current thread until all actions dispatched thus far to all + # the given Agents, from this thread or nested by the given Agents, have + # occurred, or the timeout (in seconds) has elapsed. + # + # @param [Float] timeout the maximum number of seconds to wait + # @param [Array] agents the Agents on which to wait + # @return [Boolean] true if all actions complete before timeout else false + # + # @!macro agent_await_warning + def await_for(timeout, *agents) + end_at = Concurrent.monotonic_time + timeout.to_f + ok = agents.length.times do |i| + break false if (delay = end_at - Concurrent.monotonic_time) < 0 + break false unless agents[i].await_for(delay) + end + !!ok + end + + # Blocks the current thread until all actions dispatched thus far to all + # the given Agents, from this thread or nested by the given Agents, have + # occurred, or the timeout (in seconds) has elapsed. + # + # @param [Float] timeout the maximum number of seconds to wait + # @param [Array] agents the Agents on which to wait + # @return [Boolean] true if all actions complete before timeout + # + # @raise [Concurrent::TimeoutError] when timout is reached + # @!macro agent_await_warning + def await_for!(timeout, *agents) + raise Concurrent::TimeoutError unless await_for(timeout, *agents) + true + end + end + + private + + def ns_initialize(initial, opts) + @error_mode = opts[:error_mode] + @error_handler = opts[:error_handler] + + if @error_mode && !ERROR_MODES.include?(@error_mode) + raise ArgumentError.new('unrecognized error mode') + elsif @error_mode.nil? + @error_mode = @error_handler ? :continue : :fail + end + + @error_handler ||= DEFAULT_ERROR_HANDLER + @validator = opts.fetch(:validator, DEFAULT_VALIDATOR) + @current = Concurrent::AtomicReference.new(initial) + @error = Concurrent::AtomicReference.new(nil) + @caller = Concurrent::ThreadLocalVar.new(nil) + @queue = [] + + self.observers = Collection::CopyOnNotifyObserverSet.new + end + + def enqueue_action_job(action, args, executor) + raise ArgumentError.new('no action given') unless action + job = Job.new(action, args, executor, @caller.value || Thread.current.object_id) + synchronize { ns_enqueue_job(job) } + end + + def enqueue_await_job(latch) + synchronize do + if (index = ns_find_last_job_for_thread) + job = Job.new(AWAIT_ACTION, [latch], Concurrent.global_immediate_executor, + Thread.current.object_id) + ns_enqueue_job(job, index+1) + else + latch.count_down + true + end + end + end + + def ns_enqueue_job(job, index = nil) + # a non-nil index means this is an await job + return false if index.nil? && failed? + index ||= @queue.length + @queue.insert(index, job) + # if this is the only job, post to executor + ns_post_next_job if @queue.length == 1 + true + end + + def ns_post_next_job + @queue.first.executor.post { execute_next_job } + end + + def execute_next_job + job = synchronize { @queue.first } + old_value = @current.value + + @caller.value = job.caller # for nested actions + new_value = job.action.call(old_value, *job.args) + @caller.value = nil + + return if new_value == AWAIT_FLAG + + if ns_validate(new_value) + @current.value = new_value + observers.notify_observers(Time.now, old_value, new_value) + else + handle_error(ValidationError.new) + end + rescue => error + handle_error(error) + ensure + synchronize do + @queue.shift + unless failed? || @queue.empty? + ns_post_next_job + end + end + end + + def ns_validate(value) + @validator.call(value) + rescue + false + end + + def handle_error(error) + # stop new jobs from posting + @error.value = error if @error_mode == :fail + @error_handler.call(self, error) + rescue + # do nothing + end + + def ns_find_last_job_for_thread + @queue.rindex { |job| job.caller == Thread.current.object_id } + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/array.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/array.rb new file mode 100644 index 0000000000000..c8761af8a6e22 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/array.rb @@ -0,0 +1,56 @@ +require 'concurrent/utility/engine' +require 'concurrent/thread_safe/util' + +module Concurrent + + # @!macro concurrent_array + # + # A thread-safe subclass of Array. This version locks against the object + # itself for every method call, ensuring only one thread can be reading + # or writing at a time. This includes iteration methods like `#each`. + # + # @note `a += b` is **not** a **thread-safe** operation on + # `Concurrent::Array`. It reads array `a`, then it creates new `Concurrent::Array` + # which is concatenation of `a` and `b`, then it writes the concatenation to `a`. + # The read and write are independent operations they do not form a single atomic + # operation therefore when two `+=` operations are executed concurrently updates + # may be lost. Use `#concat` instead. + # + # @see http://ruby-doc.org/core/Array.html Ruby standard library `Array` + + # @!macro internal_implementation_note + ArrayImplementation = case + when Concurrent.on_cruby? + # Array is not fully thread-safe on CRuby, see + # https://github.com/ruby-concurrency/concurrent-ruby/issues/929 + # So we will need to add synchronization here + ::Array + + when Concurrent.on_jruby? + require 'jruby/synchronized' + + class JRubyArray < ::Array + include JRuby::Synchronized + end + JRubyArray + + when Concurrent.on_truffleruby? + require 'concurrent/thread_safe/util/data_structures' + + class TruffleRubyArray < ::Array + end + + ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubyArray + TruffleRubyArray + + else + warn 'Possibly unsupported Ruby implementation' + ::Array + end + private_constant :ArrayImplementation + + # @!macro concurrent_array + class Array < ArrayImplementation + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/async.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/async.rb new file mode 100644 index 0000000000000..f9f8adf00d4e7 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/async.rb @@ -0,0 +1,449 @@ +require 'concurrent/configuration' +require 'concurrent/ivar' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # A mixin module that provides simple asynchronous behavior to a class, + # turning it into a simple actor. Loosely based on Erlang's + # [gen_server](http://www.erlang.org/doc/man/gen_server.html), but without + # supervision or linking. + # + # A more feature-rich {Concurrent::Actor} is also available when the + # capabilities of `Async` are too limited. + # + # ```cucumber + # Feature: + # As a stateful, plain old Ruby class + # I want safe, asynchronous behavior + # So my long-running methods don't block the main thread + # ``` + # + # The `Async` module is a way to mix simple yet powerful asynchronous + # capabilities into any plain old Ruby object or class, turning each object + # into a simple Actor. Method calls are processed on a background thread. The + # caller is free to perform other actions while processing occurs in the + # background. + # + # Method calls to the asynchronous object are made via two proxy methods: + # `async` (alias `cast`) and `await` (alias `call`). These proxy methods post + # the method call to the object's background thread and return a "future" + # which will eventually contain the result of the method call. + # + # This behavior is loosely patterned after Erlang's `gen_server` behavior. + # When an Erlang module implements the `gen_server` behavior it becomes + # inherently asynchronous. The `start` or `start_link` function spawns a + # process (similar to a thread but much more lightweight and efficient) and + # returns the ID of the process. Using the process ID, other processes can + # send messages to the `gen_server` via the `cast` and `call` methods. Unlike + # Erlang's `gen_server`, however, `Async` classes do not support linking or + # supervision trees. + # + # ## Basic Usage + # + # When this module is mixed into a class, objects of the class become inherently + # asynchronous. Each object gets its own background thread on which to post + # asynchronous method calls. Asynchronous method calls are executed in the + # background one at a time in the order they are received. + # + # To create an asynchronous class, simply mix in the `Concurrent::Async` module: + # + # ``` + # class Hello + # include Concurrent::Async + # + # def hello(name) + # "Hello, #{name}!" + # end + # end + # ``` + # + # Mixing this module into a class provides each object two proxy methods: + # `async` and `await`. These methods are thread safe with respect to the + # enclosing object. The former proxy allows methods to be called + # asynchronously by posting to the object's internal thread. The latter proxy + # allows a method to be called synchronously but does so safely with respect + # to any pending asynchronous method calls and ensures proper ordering. Both + # methods return a {Concurrent::IVar} which can be inspected for the result + # of the proxied method call. Calling a method with `async` will return a + # `:pending` `IVar` whereas `await` will return a `:complete` `IVar`. + # + # ``` + # class Echo + # include Concurrent::Async + # + # def echo(msg) + # print "#{msg}\n" + # end + # end + # + # horn = Echo.new + # horn.echo('zero') # synchronous, not thread-safe + # # returns the actual return value of the method + # + # horn.async.echo('one') # asynchronous, non-blocking, thread-safe + # # returns an IVar in the :pending state + # + # horn.await.echo('two') # synchronous, blocking, thread-safe + # # returns an IVar in the :complete state + # ``` + # + # ## Let It Fail + # + # The `async` and `await` proxy methods have built-in error protection based + # on Erlang's famous "let it fail" philosophy. Instance methods should not be + # programmed defensively. When an exception is raised by a delegated method + # the proxy will rescue the exception, expose it to the caller as the `reason` + # attribute of the returned future, then process the next method call. + # + # ## Calling Methods Internally + # + # External method calls should *always* use the `async` and `await` proxy + # methods. When one method calls another method, the `async` proxy should + # rarely be used and the `await` proxy should *never* be used. + # + # When an object calls one of its own methods using the `await` proxy the + # second call will be enqueued *behind* the currently running method call. + # Any attempt to wait on the result will fail as the second call will never + # run until after the current call completes. + # + # Calling a method using the `await` proxy from within a method that was + # itself called using `async` or `await` will irreversibly deadlock the + # object. Do *not* do this, ever. + # + # ## Instance Variables and Attribute Accessors + # + # Instance variables do not need to be thread-safe so long as they are private. + # Asynchronous method calls are processed in the order they are received and + # are processed one at a time. Therefore private instance variables can only + # be accessed by one thread at a time. This is inherently thread-safe. + # + # When using private instance variables within asynchronous methods, the best + # practice is to read the instance variable into a local variable at the start + # of the method then update the instance variable at the *end* of the method. + # This way, should an exception be raised during method execution the internal + # state of the object will not have been changed. + # + # ### Reader Attributes + # + # The use of `attr_reader` is discouraged. Internal state exposed externally, + # when necessary, should be done through accessor methods. The instance + # variables exposed by these methods *must* be thread-safe, or they must be + # called using the `async` and `await` proxy methods. These two approaches are + # subtly different. + # + # When internal state is accessed via the `async` and `await` proxy methods, + # the returned value represents the object's state *at the time the call is + # processed*, which may *not* be the state of the object at the time the call + # is made. + # + # To get the state *at the current* time, irrespective of an enqueued method + # calls, a reader method must be called directly. This is inherently unsafe + # unless the instance variable is itself thread-safe, preferably using one + # of the thread-safe classes within this library. Because the thread-safe + # classes within this library are internally-locking or non-locking, they can + # be safely used from within asynchronous methods without causing deadlocks. + # + # Generally speaking, the best practice is to *not* expose internal state via + # reader methods. The best practice is to simply use the method's return value. + # + # ### Writer Attributes + # + # Writer attributes should never be used with asynchronous classes. Changing + # the state externally, even when done in the thread-safe way, is not logically + # consistent. Changes to state need to be timed with respect to all asynchronous + # method calls which my be in-process or enqueued. The only safe practice is to + # pass all necessary data to each method as arguments and let the method update + # the internal state as necessary. + # + # ## Class Constants, Variables, and Methods + # + # ### Class Constants + # + # Class constants do not need to be thread-safe. Since they are read-only and + # immutable they may be safely read both externally and from within + # asynchronous methods. + # + # ### Class Variables + # + # Class variables should be avoided. Class variables represent shared state. + # Shared state is anathema to concurrency. Should there be a need to share + # state using class variables they *must* be thread-safe, preferably + # using the thread-safe classes within this library. When updating class + # variables, never assign a new value/object to the variable itself. Assignment + # is not thread-safe in Ruby. Instead, use the thread-safe update functions + # of the variable itself to change the value. + # + # The best practice is to *never* use class variables with `Async` classes. + # + # ### Class Methods + # + # Class methods which are pure functions are safe. Class methods which modify + # class variables should be avoided, for all the reasons listed above. + # + # ## An Important Note About Thread Safe Guarantees + # + # > Thread safe guarantees can only be made when asynchronous method calls + # > are not mixed with direct method calls. Use only direct method calls + # > when the object is used exclusively on a single thread. Use only + # > `async` and `await` when the object is shared between threads. Once you + # > call a method using `async` or `await`, you should no longer call methods + # > directly on the object. Use `async` and `await` exclusively from then on. + # + # @example + # + # class Echo + # include Concurrent::Async + # + # def echo(msg) + # print "#{msg}\n" + # end + # end + # + # horn = Echo.new + # horn.echo('zero') # synchronous, not thread-safe + # # returns the actual return value of the method + # + # horn.async.echo('one') # asynchronous, non-blocking, thread-safe + # # returns an IVar in the :pending state + # + # horn.await.echo('two') # synchronous, blocking, thread-safe + # # returns an IVar in the :complete state + # + # @see Concurrent::Actor + # @see https://en.wikipedia.org/wiki/Actor_model "Actor Model" at Wikipedia + # @see http://www.erlang.org/doc/man/gen_server.html Erlang gen_server + # @see http://c2.com/cgi/wiki?LetItCrash "Let It Crash" at http://c2.com/ + module Async + + # @!method self.new(*args, &block) + # + # Instanciate a new object and ensure proper initialization of the + # synchronization mechanisms. + # + # @param [Array] args Zero or more arguments to be passed to the + # object's initializer. + # @param [Proc] block Optional block to pass to the object's initializer. + # @return [Object] A properly initialized object of the asynchronous class. + + # Check for the presence of a method on an object and determine if a given + # set of arguments matches the required arity. + # + # @param [Object] obj the object to check against + # @param [Symbol] method the method to check the object for + # @param [Array] args zero or more arguments for the arity check + # + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + # + # @note This check is imperfect because of the way Ruby reports the arity of + # methods with a variable number of arguments. It is possible to determine + # if too few arguments are given but impossible to determine if too many + # arguments are given. This check may also fail to recognize dynamic behavior + # of the object, such as methods simulated with `method_missing`. + # + # @see http://www.ruby-doc.org/core-2.1.1/Method.html#method-i-arity Method#arity + # @see http://ruby-doc.org/core-2.1.0/Object.html#method-i-respond_to-3F Object#respond_to? + # @see http://www.ruby-doc.org/core-2.1.0/BasicObject.html#method-i-method_missing BasicObject#method_missing + # + # @!visibility private + def self.validate_argc(obj, method, *args) + argc = args.length + arity = obj.method(method).arity + + if arity >= 0 && argc != arity + raise ArgumentError.new("wrong number of arguments (#{argc} for #{arity})") + elsif arity < 0 && (arity = (arity + 1).abs) > argc + raise ArgumentError.new("wrong number of arguments (#{argc} for #{arity}..*)") + end + end + + # @!visibility private + def self.included(base) + base.singleton_class.send(:alias_method, :original_new, :new) + base.extend(ClassMethods) + super(base) + end + + # @!visibility private + module ClassMethods + def new(*args, &block) + obj = original_new(*args, &block) + obj.send(:init_synchronization) + obj + end + ruby2_keywords :new if respond_to?(:ruby2_keywords, true) + end + private_constant :ClassMethods + + # Delegates asynchronous, thread-safe method calls to the wrapped object. + # + # @!visibility private + class AsyncDelegator < Synchronization::LockableObject + safe_initialization! + + # Create a new delegator object wrapping the given delegate. + # + # @param [Object] delegate the object to wrap and delegate method calls to + def initialize(delegate) + super() + @delegate = delegate + @queue = [] + @executor = Concurrent.global_io_executor + @ruby_pid = $$ + end + + # Delegates method calls to the wrapped object. + # + # @param [Symbol] method the method being called + # @param [Array] args zero or more arguments to the method + # + # @return [IVar] the result of the method call + # + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + def method_missing(method, *args, &block) + super unless @delegate.respond_to?(method) + Async::validate_argc(@delegate, method, *args) + + ivar = Concurrent::IVar.new + synchronize do + reset_if_forked + @queue.push [ivar, method, args, block] + @executor.post { perform } if @queue.length == 1 + end + + ivar + end + + # Check whether the method is responsive + # + # @param [Symbol] method the method being called + def respond_to_missing?(method, include_private = false) + @delegate.respond_to?(method) || super + end + + # Perform all enqueued tasks. + # + # This method must be called from within the executor. It must not be + # called while already running. It will loop until the queue is empty. + def perform + loop do + ivar, method, args, block = synchronize { @queue.first } + break unless ivar # queue is empty + + begin + ivar.set(@delegate.send(method, *args, &block)) + rescue => error + ivar.fail(error) + end + + synchronize do + @queue.shift + return if @queue.empty? + end + end + end + + def reset_if_forked + if $$ != @ruby_pid + @queue.clear + @ruby_pid = $$ + end + end + end + private_constant :AsyncDelegator + + # Delegates synchronous, thread-safe method calls to the wrapped object. + # + # @!visibility private + class AwaitDelegator + + # Create a new delegator object wrapping the given delegate. + # + # @param [AsyncDelegator] delegate the object to wrap and delegate method calls to + def initialize(delegate) + @delegate = delegate + end + + # Delegates method calls to the wrapped object. + # + # @param [Symbol] method the method being called + # @param [Array] args zero or more arguments to the method + # + # @return [IVar] the result of the method call + # + # @raise [NameError] the object does not respond to `method` method + # @raise [ArgumentError] the given `args` do not match the arity of `method` + def method_missing(method, *args, &block) + ivar = @delegate.send(method, *args, &block) + ivar.wait + ivar + end + + # Check whether the method is responsive + # + # @param [Symbol] method the method being called + def respond_to_missing?(method, include_private = false) + @delegate.respond_to?(method) || super + end + end + private_constant :AwaitDelegator + + # Causes the chained method call to be performed asynchronously on the + # object's thread. The delegated method will return a future in the + # `:pending` state and the method call will have been scheduled on the + # object's thread. The final disposition of the method call can be obtained + # by inspecting the returned future. + # + # @!macro async_thread_safety_warning + # @note The method call is guaranteed to be thread safe with respect to + # all other method calls against the same object that are called with + # either `async` or `await`. The mutable nature of Ruby references + # (and object orientation in general) prevent any other thread safety + # guarantees. Do NOT mix direct method calls with delegated method calls. + # Use *only* delegated method calls when sharing the object between threads. + # + # @return [Concurrent::IVar] the pending result of the asynchronous operation + # + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of + # the requested method + def async + @__async_delegator__ + end + alias_method :cast, :async + + # Causes the chained method call to be performed synchronously on the + # current thread. The delegated will return a future in either the + # `:fulfilled` or `:rejected` state and the delegated method will have + # completed. The final disposition of the delegated method can be obtained + # by inspecting the returned future. + # + # @!macro async_thread_safety_warning + # + # @return [Concurrent::IVar] the completed result of the synchronous operation + # + # @raise [NameError] the object does not respond to the requested method + # @raise [ArgumentError] the given `args` do not match the arity of the + # requested method + def await + @__await_delegator__ + end + alias_method :call, :await + + # Initialize the internal serializer and other stnchronization mechanisms. + # + # @note This method *must* be called immediately upon object construction. + # This is the only way thread-safe initialization can be guaranteed. + # + # @!visibility private + def init_synchronization + return self if defined?(@__async_initialized__) && @__async_initialized__ + @__async_initialized__ = true + @__async_delegator__ = AsyncDelegator.new(self) + @__await_delegator__ = AwaitDelegator.new(@__async_delegator__) + self + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atom.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atom.rb new file mode 100644 index 0000000000000..1074006d76a04 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atom.rb @@ -0,0 +1,222 @@ +require 'concurrent/atomic/atomic_reference' +require 'concurrent/collection/copy_on_notify_observer_set' +require 'concurrent/concern/observable' +require 'concurrent/synchronization/object' + +# @!macro thread_safe_variable_comparison +# +# ## Thread-safe Variable Classes +# +# Each of the thread-safe variable classes is designed to solve a different +# problem. In general: +# +# * *{Concurrent::Agent}:* Shared, mutable variable providing independent, +# uncoordinated, *asynchronous* change of individual values. Best used when +# the value will undergo frequent, complex updates. Suitable when the result +# of an update does not need to be known immediately. +# * *{Concurrent::Atom}:* Shared, mutable variable providing independent, +# uncoordinated, *synchronous* change of individual values. Best used when +# the value will undergo frequent reads but only occasional, though complex, +# updates. Suitable when the result of an update must be known immediately. +# * *{Concurrent::AtomicReference}:* A simple object reference that can be updated +# atomically. Updates are synchronous but fast. Best used when updates a +# simple set operations. Not suitable when updates are complex. +# {Concurrent::AtomicBoolean} and {Concurrent::AtomicFixnum} are similar +# but optimized for the given data type. +# * *{Concurrent::Exchanger}:* Shared, stateless synchronization point. Used +# when two or more threads need to exchange data. The threads will pair then +# block on each other until the exchange is complete. +# * *{Concurrent::MVar}:* Shared synchronization point. Used when one thread +# must give a value to another, which must take the value. The threads will +# block on each other until the exchange is complete. +# * *{Concurrent::ThreadLocalVar}:* Shared, mutable, isolated variable which +# holds a different value for each thread which has access. Often used as +# an instance variable in objects which must maintain different state +# for different threads. +# * *{Concurrent::TVar}:* Shared, mutable variables which provide +# *coordinated*, *synchronous*, change of *many* stated. Used when multiple +# value must change together, in an all-or-nothing transaction. + + +module Concurrent + + # Atoms provide a way to manage shared, synchronous, independent state. + # + # An atom is initialized with an initial value and an optional validation + # proc. At any time the value of the atom can be synchronously and safely + # changed. If a validator is given at construction then any new value + # will be checked against the validator and will be rejected if the + # validator returns false or raises an exception. + # + # There are two ways to change the value of an atom: {#compare_and_set} and + # {#swap}. The former will set the new value if and only if it validates and + # the current value matches the new value. The latter will atomically set the + # new value to the result of running the given block if and only if that + # value validates. + # + # ## Example + # + # ``` + # def next_fibonacci(set = nil) + # return [0, 1] if set.nil? + # set + [set[-2..-1].reduce{|sum,x| sum + x }] + # end + # + # # create an atom with an initial value + # atom = Concurrent::Atom.new(next_fibonacci) + # + # # send a few update requests + # 5.times do + # atom.swap{|set| next_fibonacci(set) } + # end + # + # # get the current value + # atom.value #=> [0, 1, 1, 2, 3, 5, 8] + # ``` + # + # ## Observation + # + # Atoms support observers through the {Concurrent::Observable} mixin module. + # Notification of observers occurs every time the value of the Atom changes. + # When notified the observer will receive three arguments: `time`, `old_value`, + # and `new_value`. The `time` argument is the time at which the value change + # occurred. The `old_value` is the value of the Atom when the change began + # The `new_value` is the value to which the Atom was set when the change + # completed. Note that `old_value` and `new_value` may be the same. This is + # not an error. It simply means that the change operation returned the same + # value. + # + # Unlike in Clojure, `Atom` cannot participate in {Concurrent::TVar} transactions. + # + # @!macro thread_safe_variable_comparison + # + # @see http://clojure.org/atoms Clojure Atoms + # @see http://clojure.org/state Values and Change - Clojure's approach to Identity and State + class Atom < Synchronization::Object + include Concern::Observable + + safe_initialization! + attr_atomic(:value) + private :value=, :swap_value, :compare_and_set_value, :update_value + public :value + alias_method :deref, :value + + # @!method value + # The current value of the atom. + # + # @return [Object] The current value. + + # Create a new atom with the given initial value. + # + # @param [Object] value The initial value + # @param [Hash] opts The options used to configure the atom + # @option opts [Proc] :validator (nil) Optional proc used to validate new + # values. It must accept one and only one argument which will be the + # intended new value. The validator will return true if the new value + # is acceptable else return false (preferrably) or raise an exception. + # + # @!macro deref_options + # + # @raise [ArgumentError] if the validator is not a `Proc` (when given) + def initialize(value, opts = {}) + super() + @Validator = opts.fetch(:validator, -> v { true }) + self.observers = Collection::CopyOnNotifyObserverSet.new + self.value = value + end + + # Atomically swaps the value of atom using the given block. The current + # value will be passed to the block, as will any arguments passed as + # arguments to the function. The new value will be validated against the + # (optional) validator proc given at construction. If validation fails the + # value will not be changed. + # + # Internally, {#swap} reads the current value, applies the block to it, and + # attempts to compare-and-set it in. Since another thread may have changed + # the value in the intervening time, it may have to retry, and does so in a + # spin loop. The net effect is that the value will always be the result of + # the application of the supplied block to a current value, atomically. + # However, because the block might be called multiple times, it must be free + # of side effects. + # + # @note The given block may be called multiple times, and thus should be free + # of side effects. + # + # @param [Object] args Zero or more arguments passed to the block. + # + # @yield [value, args] Calculates a new value for the atom based on the + # current value and any supplied arguments. + # @yieldparam value [Object] The current value of the atom. + # @yieldparam args [Object] All arguments passed to the function, in order. + # @yieldreturn [Object] The intended new value of the atom. + # + # @return [Object] The final value of the atom after all operations and + # validations are complete. + # + # @raise [ArgumentError] When no block is given. + def swap(*args) + raise ArgumentError.new('no block given') unless block_given? + + loop do + old_value = value + new_value = yield(old_value, *args) + begin + break old_value unless valid?(new_value) + break new_value if compare_and_set(old_value, new_value) + rescue + break old_value + end + end + end + + # Atomically sets the value of atom to the new value if and only if the + # current value of the atom is identical to the old value and the new + # value successfully validates against the (optional) validator given + # at construction. + # + # @param [Object] old_value The expected current value. + # @param [Object] new_value The intended new value. + # + # @return [Boolean] True if the value is changed else false. + def compare_and_set(old_value, new_value) + if valid?(new_value) && compare_and_set_value(old_value, new_value) + observers.notify_observers(Time.now, old_value, new_value) + true + else + false + end + end + + # Atomically sets the value of atom to the new value without regard for the + # current value so long as the new value successfully validates against the + # (optional) validator given at construction. + # + # @param [Object] new_value The intended new value. + # + # @return [Object] The final value of the atom after all operations and + # validations are complete. + def reset(new_value) + old_value = value + if valid?(new_value) + self.value = new_value + observers.notify_observers(Time.now, old_value, new_value) + new_value + else + old_value + end + end + + private + + # Is the new value valid? + # + # @param [Object] new_value The intended new value. + # @return [Boolean] false if the validator function returns false or raises + # an exception else true + def valid?(new_value) + @Validator.call(new_value) + rescue + false + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb new file mode 100644 index 0000000000000..f775691a2a6a5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb @@ -0,0 +1,127 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/atomic/mutex_atomic_boolean' + +module Concurrent + + ################################################################### + + # @!macro atomic_boolean_method_initialize + # + # Creates a new `AtomicBoolean` with the given initial value. + # + # @param [Boolean] initial the initial value + + # @!macro atomic_boolean_method_value_get + # + # Retrieves the current `Boolean` value. + # + # @return [Boolean] the current value + + # @!macro atomic_boolean_method_value_set + # + # Explicitly sets the value. + # + # @param [Boolean] value the new value to be set + # + # @return [Boolean] the current value + + # @!macro atomic_boolean_method_true_question + # + # Is the current value `true` + # + # @return [Boolean] true if the current value is `true`, else false + + # @!macro atomic_boolean_method_false_question + # + # Is the current value `false` + # + # @return [Boolean] true if the current value is `false`, else false + + # @!macro atomic_boolean_method_make_true + # + # Explicitly sets the value to true. + # + # @return [Boolean] true if value has changed, otherwise false + + # @!macro atomic_boolean_method_make_false + # + # Explicitly sets the value to false. + # + # @return [Boolean] true if value has changed, otherwise false + + ################################################################### + + # @!macro atomic_boolean_public_api + # + # @!method initialize(initial = false) + # @!macro atomic_boolean_method_initialize + # + # @!method value + # @!macro atomic_boolean_method_value_get + # + # @!method value=(value) + # @!macro atomic_boolean_method_value_set + # + # @!method true? + # @!macro atomic_boolean_method_true_question + # + # @!method false? + # @!macro atomic_boolean_method_false_question + # + # @!method make_true + # @!macro atomic_boolean_method_make_true + # + # @!method make_false + # @!macro atomic_boolean_method_make_false + + ################################################################### + + # @!visibility private + # @!macro internal_implementation_note + AtomicBooleanImplementation = case + when Concurrent.on_cruby? && Concurrent.c_extensions_loaded? + CAtomicBoolean + when Concurrent.on_jruby? + JavaAtomicBoolean + else + MutexAtomicBoolean + end + private_constant :AtomicBooleanImplementation + + # @!macro atomic_boolean + # + # A boolean value that can be updated atomically. Reads and writes to an atomic + # boolean and thread-safe and guaranteed to succeed. Reads and writes may block + # briefly but no explicit locking is required. + # + # @!macro thread_safe_variable_comparison + # + # Performance: + # + # ``` + # Testing with ruby 2.1.2 + # Testing with Concurrent::MutexAtomicBoolean... + # 2.790000 0.000000 2.790000 ( 2.791454) + # Testing with Concurrent::CAtomicBoolean... + # 0.740000 0.000000 0.740000 ( 0.740206) + # + # Testing with jruby 1.9.3 + # Testing with Concurrent::MutexAtomicBoolean... + # 5.240000 2.520000 7.760000 ( 3.683000) + # Testing with Concurrent::JavaAtomicBoolean... + # 3.340000 0.010000 3.350000 ( 0.855000) + # ``` + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html java.util.concurrent.atomic.AtomicBoolean + # + # @!macro atomic_boolean_public_api + class AtomicBoolean < AtomicBooleanImplementation + # @return [String] Short string representation. + def to_s + format '%s value:%s>', super[0..-2], value + end + + alias_method :inspect, :to_s + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb new file mode 100644 index 0000000000000..26cd05d869213 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb @@ -0,0 +1,144 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/atomic/mutex_atomic_fixnum' + +module Concurrent + + ################################################################### + + # @!macro atomic_fixnum_method_initialize + # + # Creates a new `AtomicFixnum` with the given initial value. + # + # @param [Fixnum] initial the initial value + # @raise [ArgumentError] if the initial value is not a `Fixnum` + + # @!macro atomic_fixnum_method_value_get + # + # Retrieves the current `Fixnum` value. + # + # @return [Fixnum] the current value + + # @!macro atomic_fixnum_method_value_set + # + # Explicitly sets the value. + # + # @param [Fixnum] value the new value to be set + # + # @return [Fixnum] the current value + # + # @raise [ArgumentError] if the new value is not a `Fixnum` + + # @!macro atomic_fixnum_method_increment + # + # Increases the current value by the given amount (defaults to 1). + # + # @param [Fixnum] delta the amount by which to increase the current value + # + # @return [Fixnum] the current value after incrementation + + # @!macro atomic_fixnum_method_decrement + # + # Decreases the current value by the given amount (defaults to 1). + # + # @param [Fixnum] delta the amount by which to decrease the current value + # + # @return [Fixnum] the current value after decrementation + + # @!macro atomic_fixnum_method_compare_and_set + # + # Atomically sets the value to the given updated value if the current + # value == the expected value. + # + # @param [Fixnum] expect the expected value + # @param [Fixnum] update the new value + # + # @return [Boolean] true if the value was updated else false + + # @!macro atomic_fixnum_method_update + # + # Pass the current value to the given block, replacing it + # with the block's result. May retry if the value changes + # during the block's execution. + # + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam [Object] old_value the starting value of the atomic reference + # + # @return [Object] the new value + + ################################################################### + + # @!macro atomic_fixnum_public_api + # + # @!method initialize(initial = 0) + # @!macro atomic_fixnum_method_initialize + # + # @!method value + # @!macro atomic_fixnum_method_value_get + # + # @!method value=(value) + # @!macro atomic_fixnum_method_value_set + # + # @!method increment(delta = 1) + # @!macro atomic_fixnum_method_increment + # + # @!method decrement(delta = 1) + # @!macro atomic_fixnum_method_decrement + # + # @!method compare_and_set(expect, update) + # @!macro atomic_fixnum_method_compare_and_set + # + # @!method update + # @!macro atomic_fixnum_method_update + + ################################################################### + + # @!visibility private + # @!macro internal_implementation_note + AtomicFixnumImplementation = case + when Concurrent.on_cruby? && Concurrent.c_extensions_loaded? + CAtomicFixnum + when Concurrent.on_jruby? + JavaAtomicFixnum + else + MutexAtomicFixnum + end + private_constant :AtomicFixnumImplementation + + # @!macro atomic_fixnum + # + # A numeric value that can be updated atomically. Reads and writes to an atomic + # fixnum and thread-safe and guaranteed to succeed. Reads and writes may block + # briefly but no explicit locking is required. + # + # @!macro thread_safe_variable_comparison + # + # Performance: + # + # ``` + # Testing with ruby 2.1.2 + # Testing with Concurrent::MutexAtomicFixnum... + # 3.130000 0.000000 3.130000 ( 3.136505) + # Testing with Concurrent::CAtomicFixnum... + # 0.790000 0.000000 0.790000 ( 0.785550) + # + # Testing with jruby 1.9.3 + # Testing with Concurrent::MutexAtomicFixnum... + # 5.460000 2.460000 7.920000 ( 3.715000) + # Testing with Concurrent::JavaAtomicFixnum... + # 4.520000 0.030000 4.550000 ( 1.187000) + # ``` + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicLong.html java.util.concurrent.atomic.AtomicLong + # + # @!macro atomic_fixnum_public_api + class AtomicFixnum < AtomicFixnumImplementation + # @return [String] Short string representation. + def to_s + format '%s value:%s>', super[0..-2], value + end + + alias_method :inspect, :to_s + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb new file mode 100644 index 0000000000000..e16be65772c96 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb @@ -0,0 +1,167 @@ +require 'concurrent/errors' +require 'concurrent/synchronization/object' + +module Concurrent + # An atomic reference which maintains an object reference along with a mark bit + # that can be updated atomically. + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicMarkableReference.html + # java.util.concurrent.atomic.AtomicMarkableReference + class AtomicMarkableReference < ::Concurrent::Synchronization::Object + + attr_atomic(:reference) + private :reference, :reference=, :swap_reference, :compare_and_set_reference, :update_reference + + def initialize(value = nil, mark = false) + super() + self.reference = immutable_array(value, mark) + end + + # Atomically sets the value and mark to the given updated value and + # mark given both: + # - the current value == the expected value && + # - the current mark == the expected mark + # + # @param [Object] expected_val the expected value + # @param [Object] new_val the new value + # @param [Boolean] expected_mark the expected mark + # @param [Boolean] new_mark the new mark + # + # @return [Boolean] `true` if successful. A `false` return indicates + # that the actual value was not equal to the expected value or the + # actual mark was not equal to the expected mark + def compare_and_set(expected_val, new_val, expected_mark, new_mark) + # Memoize a valid reference to the current AtomicReference for + # later comparison. + current = reference + curr_val, curr_mark = current + + # Ensure that that the expected marks match. + return false unless expected_mark == curr_mark + + if expected_val.is_a? Numeric + # If the object is a numeric, we need to ensure we are comparing + # the numerical values + return false unless expected_val == curr_val + else + # Otherwise, we need to ensure we are comparing the object identity. + # Theoretically, this could be incorrect if a user monkey-patched + # `Object#equal?`, but they should know that they are playing with + # fire at that point. + return false unless expected_val.equal? curr_val + end + + prospect = immutable_array(new_val, new_mark) + + compare_and_set_reference current, prospect + end + + alias_method :compare_and_swap, :compare_and_set + + # Gets the current reference and marked values. + # + # @return [Array] the current reference and marked values + def get + reference + end + + # Gets the current value of the reference + # + # @return [Object] the current value of the reference + def value + reference[0] + end + + # Gets the current marked value + # + # @return [Boolean] the current marked value + def mark + reference[1] + end + + alias_method :marked?, :mark + + # _Unconditionally_ sets to the given value of both the reference and + # the mark. + # + # @param [Object] new_val the new value + # @param [Boolean] new_mark the new mark + # + # @return [Array] both the new value and the new mark + def set(new_val, new_mark) + self.reference = immutable_array(new_val, new_mark) + end + + # Pass the current value and marked state to the given block, replacing it + # with the block's results. May retry if the value changes during the + # block's execution. + # + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam [Object] old_val the starting value of the atomic reference + # @yieldparam [Boolean] old_mark the starting state of marked + # + # @return [Array] the new value and new mark + def update + loop do + old_val, old_mark = reference + new_val, new_mark = yield old_val, old_mark + + if compare_and_set old_val, new_val, old_mark, new_mark + return immutable_array(new_val, new_mark) + end + end + end + + # Pass the current value to the given block, replacing it + # with the block's result. Raise an exception if the update + # fails. + # + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam [Object] old_val the starting value of the atomic reference + # @yieldparam [Boolean] old_mark the starting state of marked + # + # @return [Array] the new value and marked state + # + # @raise [Concurrent::ConcurrentUpdateError] if the update fails + def try_update! + old_val, old_mark = reference + new_val, new_mark = yield old_val, old_mark + + unless compare_and_set old_val, new_val, old_mark, new_mark + fail ::Concurrent::ConcurrentUpdateError, + 'AtomicMarkableReference: Update failed due to race condition.', + 'Note: If you would like to guarantee an update, please use ' + + 'the `AtomicMarkableReference#update` method.' + end + + immutable_array(new_val, new_mark) + end + + # Pass the current value to the given block, replacing it with the + # block's result. Simply return nil if update fails. + # + # @yield [Object] Calculate a new value and marked state for the atomic + # reference using given (old) value and (old) marked + # @yieldparam [Object] old_val the starting value of the atomic reference + # @yieldparam [Boolean] old_mark the starting state of marked + # + # @return [Array] the new value and marked state, or nil if + # the update failed + def try_update + old_val, old_mark = reference + new_val, new_mark = yield old_val, old_mark + + return unless compare_and_set old_val, new_val, old_mark, new_mark + + immutable_array(new_val, new_mark) + end + + private + + def immutable_array(*args) + args.freeze + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb new file mode 100644 index 0000000000000..bb5fb774598cd --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb @@ -0,0 +1,135 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/atomic_reference/atomic_direct_update' +require 'concurrent/atomic_reference/numeric_cas_wrapper' +require 'concurrent/atomic_reference/mutex_atomic' + +# Shim for TruffleRuby::AtomicReference +if Concurrent.on_truffleruby? && !defined?(TruffleRuby::AtomicReference) + # @!visibility private + module TruffleRuby + AtomicReference = Truffle::AtomicReference + end +end + +module Concurrent + + # @!macro internal_implementation_note + AtomicReferenceImplementation = case + when Concurrent.on_cruby? && Concurrent.c_extensions_loaded? + # @!visibility private + # @!macro internal_implementation_note + class CAtomicReference + include AtomicDirectUpdate + include AtomicNumericCompareAndSetWrapper + alias_method :compare_and_swap, :compare_and_set + end + CAtomicReference + when Concurrent.on_jruby? + # @!visibility private + # @!macro internal_implementation_note + class JavaAtomicReference + include AtomicDirectUpdate + end + JavaAtomicReference + when Concurrent.on_truffleruby? + class TruffleRubyAtomicReference < TruffleRuby::AtomicReference + include AtomicDirectUpdate + alias_method :value, :get + alias_method :value=, :set + alias_method :compare_and_swap, :compare_and_set + alias_method :swap, :get_and_set + end + TruffleRubyAtomicReference + else + MutexAtomicReference + end + private_constant :AtomicReferenceImplementation + + # An object reference that may be updated atomically. All read and write + # operations have java volatile semantic. + # + # @!macro thread_safe_variable_comparison + # + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html + # + # @!method initialize(value = nil) + # @!macro atomic_reference_method_initialize + # @param [Object] value The initial value. + # + # @!method get + # @!macro atomic_reference_method_get + # Gets the current value. + # @return [Object] the current value + # + # @!method set(new_value) + # @!macro atomic_reference_method_set + # Sets to the given value. + # @param [Object] new_value the new value + # @return [Object] the new value + # + # @!method get_and_set(new_value) + # @!macro atomic_reference_method_get_and_set + # Atomically sets to the given value and returns the old value. + # @param [Object] new_value the new value + # @return [Object] the old value + # + # @!method compare_and_set(old_value, new_value) + # @!macro atomic_reference_method_compare_and_set + # + # Atomically sets the value to the given updated value if + # the current value == the expected value. + # + # @param [Object] old_value the expected value + # @param [Object] new_value the new value + # + # @return [Boolean] `true` if successful. A `false` return indicates + # that the actual value was not equal to the expected value. + # + # @!method update + # Pass the current value to the given block, replacing it + # with the block's result. May retry if the value changes + # during the block's execution. + # + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam [Object] old_value the starting value of the atomic reference + # @return [Object] the new value + # + # @!method try_update + # Pass the current value to the given block, replacing it + # with the block's result. Return nil if the update fails. + # + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam [Object] old_value the starting value of the atomic reference + # @note This method was altered to avoid raising an exception by default. + # Instead, this method now returns `nil` in case of failure. For more info, + # please see: https://github.com/ruby-concurrency/concurrent-ruby/pull/336 + # @return [Object] the new value, or nil if update failed + # + # @!method try_update! + # Pass the current value to the given block, replacing it + # with the block's result. Raise an exception if the update + # fails. + # + # @yield [Object] Calculate a new value for the atomic reference using + # given (old) value + # @yieldparam [Object] old_value the starting value of the atomic reference + # @note This behavior mimics the behavior of the original + # `AtomicReference#try_update` API. The reason this was changed was to + # avoid raising exceptions (which are inherently slow) by default. For more + # info: https://github.com/ruby-concurrency/concurrent-ruby/pull/336 + # @return [Object] the new value + # @raise [Concurrent::ConcurrentUpdateError] if the update fails + class AtomicReference < AtomicReferenceImplementation + + # @return [String] Short string representation. + def to_s + format '%s value:%s>', super[0..-2], get + end + + alias_method :inspect, :to_s + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb new file mode 100644 index 0000000000000..d883aed6f251b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb @@ -0,0 +1,100 @@ +require 'concurrent/utility/engine' +require 'concurrent/atomic/mutex_count_down_latch' +require 'concurrent/atomic/java_count_down_latch' + +module Concurrent + + ################################################################### + + # @!macro count_down_latch_method_initialize + # + # Create a new `CountDownLatch` with the initial `count`. + # + # @param [new] count the initial count + # + # @raise [ArgumentError] if `count` is not an integer or is less than zero + + # @!macro count_down_latch_method_wait + # + # Block on the latch until the counter reaches zero or until `timeout` is reached. + # + # @param [Fixnum] timeout the number of seconds to wait for the counter or `nil` + # to block indefinitely + # @return [Boolean] `true` if the `count` reaches zero else false on `timeout` + + # @!macro count_down_latch_method_count_down + # + # Signal the latch to decrement the counter. Will signal all blocked threads when + # the `count` reaches zero. + + # @!macro count_down_latch_method_count + # + # The current value of the counter. + # + # @return [Fixnum] the current value of the counter + + ################################################################### + + # @!macro count_down_latch_public_api + # + # @!method initialize(count = 1) + # @!macro count_down_latch_method_initialize + # + # @!method wait(timeout = nil) + # @!macro count_down_latch_method_wait + # + # @!method count_down + # @!macro count_down_latch_method_count_down + # + # @!method count + # @!macro count_down_latch_method_count + + ################################################################### + + # @!visibility private + # @!macro internal_implementation_note + CountDownLatchImplementation = case + when Concurrent.on_jruby? + JavaCountDownLatch + else + MutexCountDownLatch + end + private_constant :CountDownLatchImplementation + + # @!macro count_down_latch + # + # A synchronization object that allows one thread to wait on multiple other threads. + # The thread that will wait creates a `CountDownLatch` and sets the initial value + # (normally equal to the number of other threads). The initiating thread passes the + # latch to the other threads then waits for the other threads by calling the `#wait` + # method. Each of the other threads calls `#count_down` when done with its work. + # When the latch counter reaches zero the waiting thread is unblocked and continues + # with its work. A `CountDownLatch` can be used only once. Its value cannot be reset. + # + # @!macro count_down_latch_public_api + # @example Waiter and Decrementer + # latch = Concurrent::CountDownLatch.new(3) + # + # waiter = Thread.new do + # latch.wait() + # puts ("Waiter released") + # end + # + # decrementer = Thread.new do + # sleep(1) + # latch.count_down + # puts latch.count + # + # sleep(1) + # latch.count_down + # puts latch.count + # + # sleep(1) + # latch.count_down + # puts latch.count + # end + # + # [waiter, decrementer].each(&:join) + class CountDownLatch < CountDownLatchImplementation + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb new file mode 100644 index 0000000000000..9ebe29dd09816 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb @@ -0,0 +1,128 @@ +require 'concurrent/synchronization/lockable_object' +require 'concurrent/utility/native_integer' + +module Concurrent + + # A synchronization aid that allows a set of threads to all wait for each + # other to reach a common barrier point. + # @example + # barrier = Concurrent::CyclicBarrier.new(3) + # jobs = Array.new(3) { |i| -> { sleep i; p done: i } } + # process = -> (i) do + # # waiting to start at the same time + # barrier.wait + # # execute job + # jobs[i].call + # # wait for others to finish + # barrier.wait + # end + # threads = 2.times.map do |i| + # Thread.new(i, &process) + # end + # + # # use main as well + # process.call 2 + # + # # here we can be sure that all jobs are processed + class CyclicBarrier < Synchronization::LockableObject + + # @!visibility private + Generation = Struct.new(:status) + private_constant :Generation + + # Create a new `CyclicBarrier` that waits for `parties` threads + # + # @param [Fixnum] parties the number of parties + # @yield an optional block that will be executed that will be executed after + # the last thread arrives and before the others are released + # + # @raise [ArgumentError] if `parties` is not an integer or is less than zero + def initialize(parties, &block) + Utility::NativeInteger.ensure_integer_and_bounds parties + Utility::NativeInteger.ensure_positive_and_no_zero parties + + super(&nil) + synchronize { ns_initialize parties, &block } + end + + # @return [Fixnum] the number of threads needed to pass the barrier + def parties + synchronize { @parties } + end + + # @return [Fixnum] the number of threads currently waiting on the barrier + def number_waiting + synchronize { @number_waiting } + end + + # Blocks on the barrier until the number of waiting threads is equal to + # `parties` or until `timeout` is reached or `reset` is called + # If a block has been passed to the constructor, it will be executed once by + # the last arrived thread before releasing the others + # @param [Fixnum] timeout the number of seconds to wait for the counter or + # `nil` to block indefinitely + # @return [Boolean] `true` if the `count` reaches zero else false on + # `timeout` or on `reset` or if the barrier is broken + def wait(timeout = nil) + synchronize do + + return false unless @generation.status == :waiting + + @number_waiting += 1 + + if @number_waiting == @parties + @action.call if @action + ns_generation_done @generation, :fulfilled + true + else + generation = @generation + if ns_wait_until(timeout) { generation.status != :waiting } + generation.status == :fulfilled + else + ns_generation_done generation, :broken, false + false + end + end + end + end + + # resets the barrier to its initial state + # If there is at least one waiting thread, it will be woken up, the `wait` + # method will return false and the barrier will be broken + # If the barrier is broken, this method restores it to the original state + # + # @return [nil] + def reset + synchronize { ns_generation_done @generation, :reset } + end + + # A barrier can be broken when: + # - a thread called the `reset` method while at least one other thread was waiting + # - at least one thread timed out on `wait` method + # + # A broken barrier can be restored using `reset` it's safer to create a new one + # @return [Boolean] true if the barrier is broken otherwise false + def broken? + synchronize { @generation.status != :waiting } + end + + protected + + def ns_generation_done(generation, status, continue = true) + generation.status = status + ns_next_generation if continue + ns_broadcast + end + + def ns_next_generation + @generation = Generation.new(:waiting) + @number_waiting = 0 + end + + def ns_initialize(parties, &block) + @parties = parties + @action = block + ns_next_generation + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/event.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/event.rb new file mode 100644 index 0000000000000..ccf84c9d1b8a1 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/event.rb @@ -0,0 +1,109 @@ +require 'thread' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # Old school kernel-style event reminiscent of Win32 programming in C++. + # + # When an `Event` is created it is in the `unset` state. Threads can choose to + # `#wait` on the event, blocking until released by another thread. When one + # thread wants to alert all blocking threads it calls the `#set` method which + # will then wake up all listeners. Once an `Event` has been set it remains set. + # New threads calling `#wait` will return immediately. An `Event` may be + # `#reset` at any time once it has been set. + # + # @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx + # @example + # event = Concurrent::Event.new + # + # t1 = Thread.new do + # puts "t1 is waiting" + # event.wait(1) + # puts "event occurred" + # end + # + # t2 = Thread.new do + # puts "t2 calling set" + # event.set + # end + # + # [t1, t2].each(&:join) + # + # # prints: + # # t1 is waiting + # # t2 calling set + # # event occurred + class Event < Synchronization::LockableObject + + # Creates a new `Event` in the unset state. Threads calling `#wait` on the + # `Event` will block. + def initialize + super + synchronize { ns_initialize } + end + + # Is the object in the set state? + # + # @return [Boolean] indicating whether or not the `Event` has been set + def set? + synchronize { @set } + end + + # Trigger the event, setting the state to `set` and releasing all threads + # waiting on the event. Has no effect if the `Event` has already been set. + # + # @return [Boolean] should always return `true` + def set + synchronize { ns_set } + end + + def try? + synchronize { @set ? false : ns_set } + end + + # Reset a previously set event back to the `unset` state. + # Has no effect if the `Event` has not yet been set. + # + # @return [Boolean] should always return `true` + def reset + synchronize do + if @set + @set = false + @iteration +=1 + end + true + end + end + + # Wait a given number of seconds for the `Event` to be set by another + # thread. Will wait forever when no `timeout` value is given. Returns + # immediately if the `Event` has already been set. + # + # @return [Boolean] true if the `Event` was set before timeout else false + def wait(timeout = nil) + synchronize do + unless @set + iteration = @iteration + ns_wait_until(timeout) { iteration < @iteration || @set } + else + true + end + end + end + + protected + + def ns_set + unless @set + @set = true + ns_broadcast + end + true + end + + def ns_initialize + @set = false + @iteration = 0 + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb new file mode 100644 index 0000000000000..e90fc24f9ecb5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb @@ -0,0 +1,109 @@ +require 'concurrent/constants' +require_relative 'locals' + +module Concurrent + + # A `FiberLocalVar` is a variable where the value is different for each fiber. + # Each variable may have a default value, but when you modify the variable only + # the current fiber will ever see that change. + # + # This is similar to Ruby's built-in fiber-local variables (`Thread.current[:name]`), + # but with these major advantages: + # * `FiberLocalVar` has its own identity, it doesn't need a Symbol. + # * Each Ruby's built-in fiber-local variable leaks some memory forever (it's a Symbol held forever on the fiber), + # so it's only OK to create a small amount of them. + # `FiberLocalVar` has no such issue and it is fine to create many of them. + # * Ruby's built-in fiber-local variables leak forever the value set on each fiber (unless set to nil explicitly). + # `FiberLocalVar` automatically removes the mapping for each fiber once the `FiberLocalVar` instance is GC'd. + # + # @example + # v = FiberLocalVar.new(14) + # v.value #=> 14 + # v.value = 2 + # v.value #=> 2 + # + # @example + # v = FiberLocalVar.new(14) + # + # Fiber.new do + # v.value #=> 14 + # v.value = 1 + # v.value #=> 1 + # end.resume + # + # Fiber.new do + # v.value #=> 14 + # v.value = 2 + # v.value #=> 2 + # end.resume + # + # v.value #=> 14 + class FiberLocalVar + LOCALS = FiberLocals.new + + # Creates a fiber local variable. + # + # @param [Object] default the default value when otherwise unset + # @param [Proc] default_block Optional block that gets called to obtain the + # default value for each fiber + def initialize(default = nil, &default_block) + if default && block_given? + raise ArgumentError, "Cannot use both value and block as default value" + end + + if block_given? + @default_block = default_block + @default = nil + else + @default_block = nil + @default = default + end + + @index = LOCALS.next_index(self) + end + + # Returns the value in the current fiber's copy of this fiber-local variable. + # + # @return [Object] the current value + def value + LOCALS.fetch(@index) { default } + end + + # Sets the current fiber's copy of this fiber-local variable to the specified value. + # + # @param [Object] value the value to set + # @return [Object] the new value + def value=(value) + LOCALS.set(@index, value) + end + + # Bind the given value to fiber local storage during + # execution of the given block. + # + # @param [Object] value the value to bind + # @yield the operation to be performed with the bound variable + # @return [Object] the value + def bind(value) + if block_given? + old_value = self.value + self.value = value + begin + yield + ensure + self.value = old_value + end + end + end + + protected + + # @!visibility private + def default + if @default_block + self.value = @default_block.call + else + @default + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb new file mode 100644 index 0000000000000..3c119bc32c2c4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb @@ -0,0 +1,43 @@ +if Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + + module Concurrent + + # @!macro count_down_latch + # @!visibility private + # @!macro internal_implementation_note + class JavaCountDownLatch + + # @!macro count_down_latch_method_initialize + def initialize(count = 1) + Utility::NativeInteger.ensure_integer_and_bounds(count) + Utility::NativeInteger.ensure_positive(count) + @latch = java.util.concurrent.CountDownLatch.new(count) + end + + # @!macro count_down_latch_method_wait + def wait(timeout = nil) + result = nil + if timeout.nil? + Synchronization::JRuby.sleep_interruptibly { @latch.await } + result = true + else + Synchronization::JRuby.sleep_interruptibly do + result = @latch.await(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS) + end + end + result + end + + # @!macro count_down_latch_method_count_down + def count_down + @latch.countDown + end + + # @!macro count_down_latch_method_count + def count + @latch.getCount + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/locals.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/locals.rb new file mode 100644 index 0000000000000..0a276aedd5251 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/locals.rb @@ -0,0 +1,189 @@ +require 'fiber' +require 'concurrent/utility/engine' +require 'concurrent/constants' + +module Concurrent + # @!visibility private + # @!macro internal_implementation_note + # + # An abstract implementation of local storage, with sub-classes for + # per-thread and per-fiber locals. + # + # Each execution context (EC, thread or fiber) has a lazily initialized array + # of local variable values. Each time a new local variable is created, we + # allocate an "index" for it. + # + # For example, if the allocated index is 1, that means slot #1 in EVERY EC's + # locals array will be used for the value of that variable. + # + # The good thing about using a per-EC structure to hold values, rather than + # a global, is that no synchronization is needed when reading and writing + # those values (since the structure is only ever accessed by a single + # thread). + # + # Of course, when a local variable is GC'd, 1) we need to recover its index + # for use by other new local variables (otherwise the locals arrays could + # get bigger and bigger with time), and 2) we need to null out all the + # references held in the now-unused slots (both to avoid blocking GC of those + # objects, and also to prevent "stale" values from being passed on to a new + # local when the index is reused). + # + # Because we need to null out freed slots, we need to keep references to + # ALL the locals arrays, so we can null out the appropriate slots in all of + # them. This is why we need to use a finalizer to clean up the locals array + # when the EC goes out of scope. + class AbstractLocals + def initialize + @free = [] + @lock = Mutex.new + @all_arrays = {} + @next = 0 + end + + def synchronize + @lock.synchronize { yield } + end + + if Concurrent.on_cruby? + def weak_synchronize + yield + end + else + alias_method :weak_synchronize, :synchronize + end + + def next_index(local) + index = synchronize do + if @free.empty? + @next += 1 + else + @free.pop + end + end + + # When the local goes out of scope, we should free the associated index + # and all values stored into it. + ObjectSpace.define_finalizer(local, local_finalizer(index)) + + index + end + + def free_index(index) + weak_synchronize do + # The cost of GC'ing a TLV is linear in the number of ECs using local + # variables. But that is natural! More ECs means more storage is used + # per local variable. So naturally more CPU time is required to free + # more storage. + # + # DO NOT use each_value which might conflict with new pair assignment + # into the hash in #set method. + @all_arrays.values.each do |locals| + locals[index] = nil + end + + # free index has to be published after the arrays are cleared: + @free << index + end + end + + def fetch(index) + locals = self.locals + value = locals ? locals[index] : nil + + if nil == value + yield + elsif NULL.equal?(value) + nil + else + value + end + end + + def set(index, value) + locals = self.locals! + locals[index] = (nil == value ? NULL : value) + + value + end + + private + + # When the local goes out of scope, clean up that slot across all locals currently assigned. + def local_finalizer(index) + proc do + free_index(index) + end + end + + # When a thread/fiber goes out of scope, remove the array from @all_arrays. + def thread_fiber_finalizer(array_object_id) + proc do + weak_synchronize do + @all_arrays.delete(array_object_id) + end + end + end + + # Returns the locals for the current scope, or nil if none exist. + def locals + raise NotImplementedError + end + + # Returns the locals for the current scope, creating them if necessary. + def locals! + raise NotImplementedError + end + end + + # @!visibility private + # @!macro internal_implementation_note + # An array-backed storage of indexed variables per thread. + class ThreadLocals < AbstractLocals + def locals + Thread.current.thread_variable_get(:concurrent_thread_locals) + end + + def locals! + thread = Thread.current + locals = thread.thread_variable_get(:concurrent_thread_locals) + + unless locals + locals = thread.thread_variable_set(:concurrent_thread_locals, []) + weak_synchronize do + @all_arrays[locals.object_id] = locals + end + # When the thread goes out of scope, we should delete the associated locals: + ObjectSpace.define_finalizer(thread, thread_fiber_finalizer(locals.object_id)) + end + + locals + end + end + + # @!visibility private + # @!macro internal_implementation_note + # An array-backed storage of indexed variables per fiber. + class FiberLocals < AbstractLocals + def locals + Thread.current[:concurrent_fiber_locals] + end + + def locals! + thread = Thread.current + locals = thread[:concurrent_fiber_locals] + + unless locals + locals = thread[:concurrent_fiber_locals] = [] + weak_synchronize do + @all_arrays[locals.object_id] = locals + end + # When the fiber goes out of scope, we should delete the associated locals: + ObjectSpace.define_finalizer(Fiber.current, thread_fiber_finalizer(locals.object_id)) + end + + locals + end + end + + private_constant :AbstractLocals, :ThreadLocals, :FiberLocals +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb new file mode 100644 index 0000000000000..ebf23a2414093 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb @@ -0,0 +1,28 @@ +require 'concurrent/utility/engine' +require_relative 'fiber_local_var' +require_relative 'thread_local_var' + +module Concurrent + # @!visibility private + def self.mutex_owned_per_thread? + return false if Concurrent.on_jruby? || Concurrent.on_truffleruby? + + mutex = Mutex.new + # Lock the mutex: + mutex.synchronize do + # Check if the mutex is still owned in a child fiber: + Fiber.new { mutex.owned? }.resume + end + end + + if mutex_owned_per_thread? + LockLocalVar = ThreadLocalVar + else + LockLocalVar = FiberLocalVar + end + + # Either {FiberLocalVar} or {ThreadLocalVar} depending on whether Mutex (and Monitor) + # are held, respectively, per Fiber or per Thread. + class LockLocalVar + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb new file mode 100644 index 0000000000000..015996b06f04c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb @@ -0,0 +1,68 @@ +require 'concurrent/synchronization/safe_initialization' + +module Concurrent + + # @!macro atomic_boolean + # @!visibility private + # @!macro internal_implementation_note + class MutexAtomicBoolean + extend Concurrent::Synchronization::SafeInitialization + + # @!macro atomic_boolean_method_initialize + def initialize(initial = false) + super() + @Lock = ::Mutex.new + @value = !!initial + end + + # @!macro atomic_boolean_method_value_get + def value + synchronize { @value } + end + + # @!macro atomic_boolean_method_value_set + def value=(value) + synchronize { @value = !!value } + end + + # @!macro atomic_boolean_method_true_question + def true? + synchronize { @value } + end + + # @!macro atomic_boolean_method_false_question + def false? + synchronize { !@value } + end + + # @!macro atomic_boolean_method_make_true + def make_true + synchronize { ns_make_value(true) } + end + + # @!macro atomic_boolean_method_make_false + def make_false + synchronize { ns_make_value(false) } + end + + protected + + # @!visibility private + def synchronize + if @Lock.owned? + yield + else + @Lock.synchronize { yield } + end + end + + private + + # @!visibility private + def ns_make_value(value) + old = @value + @value = value + old != @value + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb new file mode 100644 index 0000000000000..0ca395579fe09 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb @@ -0,0 +1,81 @@ +require 'concurrent/synchronization/safe_initialization' +require 'concurrent/utility/native_integer' + +module Concurrent + + # @!macro atomic_fixnum + # @!visibility private + # @!macro internal_implementation_note + class MutexAtomicFixnum + extend Concurrent::Synchronization::SafeInitialization + + # @!macro atomic_fixnum_method_initialize + def initialize(initial = 0) + super() + @Lock = ::Mutex.new + ns_set(initial) + end + + # @!macro atomic_fixnum_method_value_get + def value + synchronize { @value } + end + + # @!macro atomic_fixnum_method_value_set + def value=(value) + synchronize { ns_set(value) } + end + + # @!macro atomic_fixnum_method_increment + def increment(delta = 1) + synchronize { ns_set(@value + delta.to_i) } + end + + alias_method :up, :increment + + # @!macro atomic_fixnum_method_decrement + def decrement(delta = 1) + synchronize { ns_set(@value - delta.to_i) } + end + + alias_method :down, :decrement + + # @!macro atomic_fixnum_method_compare_and_set + def compare_and_set(expect, update) + synchronize do + if @value == expect.to_i + @value = update.to_i + true + else + false + end + end + end + + # @!macro atomic_fixnum_method_update + def update + synchronize do + @value = yield @value + end + end + + protected + + # @!visibility private + def synchronize + if @Lock.owned? + yield + else + @Lock.synchronize { yield } + end + end + + private + + # @!visibility private + def ns_set(value) + Utility::NativeInteger.ensure_integer_and_bounds value + @value = value + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb new file mode 100644 index 0000000000000..29aa1caa4f296 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb @@ -0,0 +1,44 @@ +require 'concurrent/synchronization/lockable_object' +require 'concurrent/utility/native_integer' + +module Concurrent + + # @!macro count_down_latch + # @!visibility private + # @!macro internal_implementation_note + class MutexCountDownLatch < Synchronization::LockableObject + + # @!macro count_down_latch_method_initialize + def initialize(count = 1) + Utility::NativeInteger.ensure_integer_and_bounds count + Utility::NativeInteger.ensure_positive count + + super() + synchronize { ns_initialize count } + end + + # @!macro count_down_latch_method_wait + def wait(timeout = nil) + synchronize { ns_wait_until(timeout) { @count == 0 } } + end + + # @!macro count_down_latch_method_count_down + def count_down + synchronize do + @count -= 1 if @count > 0 + ns_broadcast if @count == 0 + end + end + + # @!macro count_down_latch_method_count + def count + synchronize { @count } + end + + protected + + def ns_initialize(count) + @count = count + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb new file mode 100644 index 0000000000000..4347289f1ed10 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb @@ -0,0 +1,131 @@ +require 'concurrent/synchronization/lockable_object' +require 'concurrent/utility/native_integer' + +module Concurrent + + # @!macro semaphore + # @!visibility private + # @!macro internal_implementation_note + class MutexSemaphore < Synchronization::LockableObject + + # @!macro semaphore_method_initialize + def initialize(count) + Utility::NativeInteger.ensure_integer_and_bounds count + + super() + synchronize { ns_initialize count } + end + + # @!macro semaphore_method_acquire + def acquire(permits = 1) + Utility::NativeInteger.ensure_integer_and_bounds permits + Utility::NativeInteger.ensure_positive permits + + synchronize do + try_acquire_timed(permits, nil) + end + + return unless block_given? + + begin + yield + ensure + release(permits) + end + end + + # @!macro semaphore_method_available_permits + def available_permits + synchronize { @free } + end + + # @!macro semaphore_method_drain_permits + # + # Acquires and returns all permits that are immediately available. + # + # @return [Integer] + def drain_permits + synchronize do + @free.tap { |_| @free = 0 } + end + end + + # @!macro semaphore_method_try_acquire + def try_acquire(permits = 1, timeout = nil) + Utility::NativeInteger.ensure_integer_and_bounds permits + Utility::NativeInteger.ensure_positive permits + + acquired = synchronize do + if timeout.nil? + try_acquire_now(permits) + else + try_acquire_timed(permits, timeout) + end + end + + return acquired unless block_given? + return unless acquired + + begin + yield + ensure + release(permits) + end + end + + # @!macro semaphore_method_release + def release(permits = 1) + Utility::NativeInteger.ensure_integer_and_bounds permits + Utility::NativeInteger.ensure_positive permits + + synchronize do + @free += permits + permits.times { ns_signal } + end + nil + end + + # Shrinks the number of available permits by the indicated reduction. + # + # @param [Fixnum] reduction Number of permits to remove. + # + # @raise [ArgumentError] if `reduction` is not an integer or is negative + # + # @raise [ArgumentError] if `@free` - `@reduction` is less than zero + # + # @return [nil] + # + # @!visibility private + def reduce_permits(reduction) + Utility::NativeInteger.ensure_integer_and_bounds reduction + Utility::NativeInteger.ensure_positive reduction + + synchronize { @free -= reduction } + nil + end + + protected + + # @!visibility private + def ns_initialize(count) + @free = count + end + + private + + # @!visibility private + def try_acquire_now(permits) + if @free >= permits + @free -= permits + true + else + false + end + end + + # @!visibility private + def try_acquire_timed(permits, timeout) + ns_wait_until(timeout) { try_acquire_now(permits) } + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb new file mode 100644 index 0000000000000..b26bd17a089ce --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb @@ -0,0 +1,255 @@ +require 'thread' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/errors' +require 'concurrent/synchronization/object' +require 'concurrent/synchronization/lock' + +module Concurrent + + # Ruby read-write lock implementation + # + # Allows any number of concurrent readers, but only one concurrent writer + # (And if the "write" lock is taken, any readers who come along will have to wait) + # + # If readers are already active when a writer comes along, the writer will wait for + # all the readers to finish before going ahead. + # Any additional readers that come when the writer is already waiting, will also + # wait (so writers are not starved). + # + # This implementation is based on `java.util.concurrent.ReentrantReadWriteLock`. + # + # @example + # lock = Concurrent::ReadWriteLock.new + # lock.with_read_lock { data.retrieve } + # lock.with_write_lock { data.modify! } + # + # @note Do **not** try to acquire the write lock while already holding a read lock + # **or** try to acquire the write lock while you already have it. + # This will lead to deadlock + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html java.util.concurrent.ReentrantReadWriteLock + class ReadWriteLock < Synchronization::Object + + # @!visibility private + WAITING_WRITER = 1 << 15 + + # @!visibility private + RUNNING_WRITER = 1 << 29 + + # @!visibility private + MAX_READERS = WAITING_WRITER - 1 + + # @!visibility private + MAX_WRITERS = RUNNING_WRITER - MAX_READERS - 1 + + safe_initialization! + + # Implementation notes: + # A goal is to make the uncontended path for both readers/writers lock-free + # Only if there is reader-writer or writer-writer contention, should locks be used + # Internal state is represented by a single integer ("counter"), and updated + # using atomic compare-and-swap operations + # When the counter is 0, the lock is free + # Each reader increments the counter by 1 when acquiring a read lock + # (and decrements by 1 when releasing the read lock) + # The counter is increased by (1 << 15) for each writer waiting to acquire the + # write lock, and by (1 << 29) if the write lock is taken + + # Create a new `ReadWriteLock` in the unlocked state. + def initialize + super() + @Counter = AtomicFixnum.new(0) # single integer which represents lock state + @ReadLock = Synchronization::Lock.new + @WriteLock = Synchronization::Lock.new + end + + # Execute a block operation within a read lock. + # + # @yield the task to be performed within the lock. + # + # @return [Object] the result of the block operation. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def with_read_lock + raise ArgumentError.new('no block given') unless block_given? + acquire_read_lock + begin + yield + ensure + release_read_lock + end + end + + # Execute a block operation within a write lock. + # + # @yield the task to be performed within the lock. + # + # @return [Object] the result of the block operation. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def with_write_lock + raise ArgumentError.new('no block given') unless block_given? + acquire_write_lock + begin + yield + ensure + release_write_lock + end + end + + # Acquire a read lock. If a write lock has been acquired will block until + # it is released. Will not block if other read locks have been acquired. + # + # @return [Boolean] true if the lock is successfully acquired + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def acquire_read_lock + while true + c = @Counter.value + raise ResourceLimitError.new('Too many reader threads') if max_readers?(c) + + # If a writer is waiting when we first queue up, we need to wait + if waiting_writer?(c) + @ReadLock.wait_until { !waiting_writer? } + + # after a reader has waited once, they are allowed to "barge" ahead of waiting writers + # but if a writer is *running*, the reader still needs to wait (naturally) + while true + c = @Counter.value + if running_writer?(c) + @ReadLock.wait_until { !running_writer? } + else + return if @Counter.compare_and_set(c, c+1) + end + end + else + break if @Counter.compare_and_set(c, c+1) + end + end + true + end + + # Release a previously acquired read lock. + # + # @return [Boolean] true if the lock is successfully released + def release_read_lock + while true + c = @Counter.value + if @Counter.compare_and_set(c, c-1) + # If one or more writers were waiting, and we were the last reader, wake a writer up + if waiting_writer?(c) && running_readers(c) == 1 + @WriteLock.signal + end + break + end + end + true + end + + # Acquire a write lock. Will block and wait for all active readers and writers. + # + # @return [Boolean] true if the lock is successfully acquired + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of writers + # is exceeded. + def acquire_write_lock + while true + c = @Counter.value + raise ResourceLimitError.new('Too many writer threads') if max_writers?(c) + + if c == 0 # no readers OR writers running + # if we successfully swap the RUNNING_WRITER bit on, then we can go ahead + break if @Counter.compare_and_set(0, RUNNING_WRITER) + elsif @Counter.compare_and_set(c, c+WAITING_WRITER) + while true + # Now we have successfully incremented, so no more readers will be able to increment + # (they will wait instead) + # However, readers OR writers could decrement right here, OR another writer could increment + @WriteLock.wait_until do + # So we have to do another check inside the synchronized section + # If a writer OR reader is running, then go to sleep + c = @Counter.value + !running_writer?(c) && !running_readers?(c) + end + + # We just came out of a wait + # If we successfully turn the RUNNING_WRITER bit on with an atomic swap, + # Then we are OK to stop waiting and go ahead + # Otherwise go back and wait again + c = @Counter.value + break if !running_writer?(c) && !running_readers?(c) && @Counter.compare_and_set(c, c+RUNNING_WRITER-WAITING_WRITER) + end + break + end + end + true + end + + # Release a previously acquired write lock. + # + # @return [Boolean] true if the lock is successfully released + def release_write_lock + return true unless running_writer? + c = @Counter.update { |counter| counter - RUNNING_WRITER } + @ReadLock.broadcast + @WriteLock.signal if waiting_writers(c) > 0 + true + end + + # Queries if the write lock is held by any thread. + # + # @return [Boolean] true if the write lock is held else false` + def write_locked? + @Counter.value >= RUNNING_WRITER + end + + # Queries whether any threads are waiting to acquire the read or write lock. + # + # @return [Boolean] true if any threads are waiting for a lock else false + def has_waiters? + waiting_writer?(@Counter.value) + end + + private + + # @!visibility private + def running_readers(c = @Counter.value) + c & MAX_READERS + end + + # @!visibility private + def running_readers?(c = @Counter.value) + (c & MAX_READERS) > 0 + end + + # @!visibility private + def running_writer?(c = @Counter.value) + c >= RUNNING_WRITER + end + + # @!visibility private + def waiting_writers(c = @Counter.value) + (c & MAX_WRITERS) / WAITING_WRITER + end + + # @!visibility private + def waiting_writer?(c = @Counter.value) + c >= WAITING_WRITER + end + + # @!visibility private + def max_readers?(c = @Counter.value) + (c & MAX_READERS) == MAX_READERS + end + + # @!visibility private + def max_writers?(c = @Counter.value) + (c & MAX_WRITERS) == MAX_WRITERS + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb new file mode 100644 index 0000000000000..6d72a3a097831 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb @@ -0,0 +1,379 @@ +require 'thread' +require 'concurrent/atomic/atomic_reference' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/errors' +require 'concurrent/synchronization/object' +require 'concurrent/synchronization/lock' +require 'concurrent/atomic/lock_local_var' + +module Concurrent + + # Re-entrant read-write lock implementation + # + # Allows any number of concurrent readers, but only one concurrent writer + # (And while the "write" lock is taken, no read locks can be obtained either. + # Hence, the write lock can also be called an "exclusive" lock.) + # + # If another thread has taken a read lock, any thread which wants a write lock + # will block until all the readers release their locks. However, once a thread + # starts waiting to obtain a write lock, any additional readers that come along + # will also wait (so writers are not starved). + # + # A thread can acquire both a read and write lock at the same time. A thread can + # also acquire a read lock OR a write lock more than once. Only when the read (or + # write) lock is released as many times as it was acquired, will the thread + # actually let it go, allowing other threads which might have been waiting + # to proceed. Therefore the lock can be upgraded by first acquiring + # read lock and then write lock and that the lock can be downgraded by first + # having both read and write lock a releasing just the write lock. + # + # If both read and write locks are acquired by the same thread, it is not strictly + # necessary to release them in the same order they were acquired. In other words, + # the following code is legal: + # + # @example + # lock = Concurrent::ReentrantReadWriteLock.new + # lock.acquire_write_lock + # lock.acquire_read_lock + # lock.release_write_lock + # # At this point, the current thread is holding only a read lock, not a write + # # lock. So other threads can take read locks, but not a write lock. + # lock.release_read_lock + # # Now the current thread is not holding either a read or write lock, so + # # another thread could potentially acquire a write lock. + # + # This implementation was inspired by `java.util.concurrent.ReentrantReadWriteLock`. + # + # @example + # lock = Concurrent::ReentrantReadWriteLock.new + # lock.with_read_lock { data.retrieve } + # lock.with_write_lock { data.modify! } + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html java.util.concurrent.ReentrantReadWriteLock + class ReentrantReadWriteLock < Synchronization::Object + + # Implementation notes: + # + # A goal is to make the uncontended path for both readers/writers mutex-free + # Only if there is reader-writer or writer-writer contention, should mutexes be used + # Otherwise, a single CAS operation is all we need to acquire/release a lock + # + # Internal state is represented by a single integer ("counter"), and updated + # using atomic compare-and-swap operations + # When the counter is 0, the lock is free + # Each thread which has one OR MORE read locks increments the counter by 1 + # (and decrements by 1 when releasing the read lock) + # The counter is increased by (1 << 15) for each writer waiting to acquire the + # write lock, and by (1 << 29) if the write lock is taken + # + # Additionally, each thread uses a thread-local variable to count how many times + # it has acquired a read lock, AND how many times it has acquired a write lock. + # It uses a similar trick; an increment of 1 means a read lock was taken, and + # an increment of (1 << 15) means a write lock was taken + # This is what makes re-entrancy possible + # + # 2 rules are followed to ensure good liveness properties: + # 1) Once a writer has queued up and is waiting for a write lock, no other thread + # can take a lock without waiting + # 2) When a write lock is released, readers are given the "first chance" to wake + # up and acquire a read lock + # Following these rules means readers and writers tend to "take turns", so neither + # can starve the other, even under heavy contention + + # @!visibility private + READER_BITS = 15 + # @!visibility private + WRITER_BITS = 14 + + # Used with @Counter: + # @!visibility private + WAITING_WRITER = 1 << READER_BITS + # @!visibility private + RUNNING_WRITER = 1 << (READER_BITS + WRITER_BITS) + # @!visibility private + MAX_READERS = WAITING_WRITER - 1 + # @!visibility private + MAX_WRITERS = RUNNING_WRITER - MAX_READERS - 1 + + # Used with @HeldCount: + # @!visibility private + WRITE_LOCK_HELD = 1 << READER_BITS + # @!visibility private + READ_LOCK_MASK = WRITE_LOCK_HELD - 1 + # @!visibility private + WRITE_LOCK_MASK = MAX_WRITERS + + safe_initialization! + + # Create a new `ReentrantReadWriteLock` in the unlocked state. + def initialize + super() + @Counter = AtomicFixnum.new(0) # single integer which represents lock state + @ReadQueue = Synchronization::Lock.new # used to queue waiting readers + @WriteQueue = Synchronization::Lock.new # used to queue waiting writers + @HeldCount = LockLocalVar.new(0) # indicates # of R & W locks held by this thread + end + + # Execute a block operation within a read lock. + # + # @yield the task to be performed within the lock. + # + # @return [Object] the result of the block operation. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def with_read_lock + raise ArgumentError.new('no block given') unless block_given? + acquire_read_lock + begin + yield + ensure + release_read_lock + end + end + + # Execute a block operation within a write lock. + # + # @yield the task to be performed within the lock. + # + # @return [Object] the result of the block operation. + # + # @raise [ArgumentError] when no block is given. + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def with_write_lock + raise ArgumentError.new('no block given') unless block_given? + acquire_write_lock + begin + yield + ensure + release_write_lock + end + end + + # Acquire a read lock. If a write lock is held by another thread, will block + # until it is released. + # + # @return [Boolean] true if the lock is successfully acquired + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of readers + # is exceeded. + def acquire_read_lock + if (held = @HeldCount.value) > 0 + # If we already have a lock, there's no need to wait + if held & READ_LOCK_MASK == 0 + # But we do need to update the counter, if we were holding a write + # lock but not a read lock + @Counter.update { |c| c + 1 } + end + @HeldCount.value = held + 1 + return true + end + + while true + c = @Counter.value + raise ResourceLimitError.new('Too many reader threads') if max_readers?(c) + + # If a writer is waiting OR running when we first queue up, we need to wait + if waiting_or_running_writer?(c) + # Before going to sleep, check again with the ReadQueue mutex held + @ReadQueue.synchronize do + @ReadQueue.ns_wait if waiting_or_running_writer? + end + # Note: the above 'synchronize' block could have used #wait_until, + # but that waits repeatedly in a loop, checking the wait condition + # each time it wakes up (to protect against spurious wakeups) + # But we are already in a loop, which is only broken when we successfully + # acquire the lock! So we don't care about spurious wakeups, and would + # rather not pay the extra overhead of using #wait_until + + # After a reader has waited once, they are allowed to "barge" ahead of waiting writers + # But if a writer is *running*, the reader still needs to wait (naturally) + while true + c = @Counter.value + if running_writer?(c) + @ReadQueue.synchronize do + @ReadQueue.ns_wait if running_writer? + end + elsif @Counter.compare_and_set(c, c+1) + @HeldCount.value = held + 1 + return true + end + end + elsif @Counter.compare_and_set(c, c+1) + @HeldCount.value = held + 1 + return true + end + end + end + + # Try to acquire a read lock and return true if we succeed. If it cannot be + # acquired immediately, return false. + # + # @return [Boolean] true if the lock is successfully acquired + def try_read_lock + if (held = @HeldCount.value) > 0 + if held & READ_LOCK_MASK == 0 + # If we hold a write lock, but not a read lock... + @Counter.update { |c| c + 1 } + end + @HeldCount.value = held + 1 + return true + else + c = @Counter.value + if !waiting_or_running_writer?(c) && @Counter.compare_and_set(c, c+1) + @HeldCount.value = held + 1 + return true + end + end + false + end + + # Release a previously acquired read lock. + # + # @return [Boolean] true if the lock is successfully released + def release_read_lock + held = @HeldCount.value = @HeldCount.value - 1 + rlocks_held = held & READ_LOCK_MASK + if rlocks_held == 0 + c = @Counter.update { |counter| counter - 1 } + # If one or more writers were waiting, and we were the last reader, wake a writer up + if waiting_or_running_writer?(c) && running_readers(c) == 0 + @WriteQueue.signal + end + elsif rlocks_held == READ_LOCK_MASK + raise IllegalOperationError, "Cannot release a read lock which is not held" + end + true + end + + # Acquire a write lock. Will block and wait for all active readers and writers. + # + # @return [Boolean] true if the lock is successfully acquired + # + # @raise [Concurrent::ResourceLimitError] if the maximum number of writers + # is exceeded. + def acquire_write_lock + if (held = @HeldCount.value) >= WRITE_LOCK_HELD + # if we already have a write (exclusive) lock, there's no need to wait + @HeldCount.value = held + WRITE_LOCK_HELD + return true + end + + while true + c = @Counter.value + raise ResourceLimitError.new('Too many writer threads') if max_writers?(c) + + # To go ahead and take the lock without waiting, there must be no writer + # running right now, AND no writers who came before us still waiting to + # acquire the lock + # Additionally, if any read locks have been taken, we must hold all of them + if held > 0 && @Counter.compare_and_set(1, c+RUNNING_WRITER) + # If we are the only one reader and successfully swap the RUNNING_WRITER bit on, then we can go ahead + @HeldCount.value = held + WRITE_LOCK_HELD + return true + elsif @Counter.compare_and_set(c, c+WAITING_WRITER) + while true + # Now we have successfully incremented, so no more readers will be able to increment + # (they will wait instead) + # However, readers OR writers could decrement right here + @WriteQueue.synchronize do + # So we have to do another check inside the synchronized section + # If a writer OR another reader is running, then go to sleep + c = @Counter.value + @WriteQueue.ns_wait if running_writer?(c) || running_readers(c) != held + end + # Note: if you are thinking of replacing the above 'synchronize' block + # with #wait_until, read the comment in #acquire_read_lock first! + + # We just came out of a wait + # If we successfully turn the RUNNING_WRITER bit on with an atomic swap, + # then we are OK to stop waiting and go ahead + # Otherwise go back and wait again + c = @Counter.value + if !running_writer?(c) && + running_readers(c) == held && + @Counter.compare_and_set(c, c+RUNNING_WRITER-WAITING_WRITER) + @HeldCount.value = held + WRITE_LOCK_HELD + return true + end + end + end + end + end + + # Try to acquire a write lock and return true if we succeed. If it cannot be + # acquired immediately, return false. + # + # @return [Boolean] true if the lock is successfully acquired + def try_write_lock + if (held = @HeldCount.value) >= WRITE_LOCK_HELD + @HeldCount.value = held + WRITE_LOCK_HELD + return true + else + c = @Counter.value + if !waiting_or_running_writer?(c) && + running_readers(c) == held && + @Counter.compare_and_set(c, c+RUNNING_WRITER) + @HeldCount.value = held + WRITE_LOCK_HELD + return true + end + end + false + end + + # Release a previously acquired write lock. + # + # @return [Boolean] true if the lock is successfully released + def release_write_lock + held = @HeldCount.value = @HeldCount.value - WRITE_LOCK_HELD + wlocks_held = held & WRITE_LOCK_MASK + if wlocks_held == 0 + c = @Counter.update { |counter| counter - RUNNING_WRITER } + @ReadQueue.broadcast + @WriteQueue.signal if waiting_writers(c) > 0 + elsif wlocks_held == WRITE_LOCK_MASK + raise IllegalOperationError, "Cannot release a write lock which is not held" + end + true + end + + private + + # @!visibility private + def running_readers(c = @Counter.value) + c & MAX_READERS + end + + # @!visibility private + def running_readers?(c = @Counter.value) + (c & MAX_READERS) > 0 + end + + # @!visibility private + def running_writer?(c = @Counter.value) + c >= RUNNING_WRITER + end + + # @!visibility private + def waiting_writers(c = @Counter.value) + (c & MAX_WRITERS) >> READER_BITS + end + + # @!visibility private + def waiting_or_running_writer?(c = @Counter.value) + c >= WAITING_WRITER + end + + # @!visibility private + def max_readers?(c = @Counter.value) + (c & MAX_READERS) == MAX_READERS + end + + # @!visibility private + def max_writers?(c = @Counter.value) + (c & MAX_WRITERS) == MAX_WRITERS + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/semaphore.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/semaphore.rb new file mode 100644 index 0000000000000..f0799f0f41a63 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/semaphore.rb @@ -0,0 +1,163 @@ +require 'concurrent/atomic/mutex_semaphore' + +module Concurrent + + ################################################################### + + # @!macro semaphore_method_initialize + # + # Create a new `Semaphore` with the initial `count`. + # + # @param [Fixnum] count the initial count + # + # @raise [ArgumentError] if `count` is not an integer + + # @!macro semaphore_method_acquire + # + # Acquires the given number of permits from this semaphore, + # blocking until all are available. If a block is given, + # yields to it and releases the permits afterwards. + # + # @param [Fixnum] permits Number of permits to acquire + # + # @raise [ArgumentError] if `permits` is not an integer or is less than zero + # + # @return [nil, BasicObject] Without a block, `nil` is returned. If a block + # is given, its return value is returned. + + # @!macro semaphore_method_available_permits + # + # Returns the current number of permits available in this semaphore. + # + # @return [Integer] + + # @!macro semaphore_method_drain_permits + # + # Acquires and returns all permits that are immediately available. + # + # @return [Integer] + + # @!macro semaphore_method_try_acquire + # + # Acquires the given number of permits from this semaphore, + # only if all are available at the time of invocation or within + # `timeout` interval. If a block is given, yields to it if the permits + # were successfully acquired, and releases them afterward, returning the + # block's return value. + # + # @param [Fixnum] permits the number of permits to acquire + # + # @param [Fixnum] timeout the number of seconds to wait for the counter + # or `nil` to return immediately + # + # @raise [ArgumentError] if `permits` is not an integer or is less than zero + # + # @return [true, false, nil, BasicObject] `false` if no permits are + # available, `true` when acquired a permit. If a block is given, the + # block's return value is returned if the permits were acquired; if not, + # `nil` is returned. + + # @!macro semaphore_method_release + # + # Releases the given number of permits, returning them to the semaphore. + # + # @param [Fixnum] permits Number of permits to return to the semaphore. + # + # @raise [ArgumentError] if `permits` is not a number or is less than zero + # + # @return [nil] + + ################################################################### + + # @!macro semaphore_public_api + # + # @!method initialize(count) + # @!macro semaphore_method_initialize + # + # @!method acquire(permits = 1) + # @!macro semaphore_method_acquire + # + # @!method available_permits + # @!macro semaphore_method_available_permits + # + # @!method drain_permits + # @!macro semaphore_method_drain_permits + # + # @!method try_acquire(permits = 1, timeout = nil) + # @!macro semaphore_method_try_acquire + # + # @!method release(permits = 1) + # @!macro semaphore_method_release + + ################################################################### + + # @!visibility private + # @!macro internal_implementation_note + SemaphoreImplementation = if Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + JavaSemaphore + else + MutexSemaphore + end + private_constant :SemaphoreImplementation + + # @!macro semaphore + # + # A counting semaphore. Conceptually, a semaphore maintains a set of + # permits. Each {#acquire} blocks if necessary until a permit is + # available, and then takes it. Each {#release} adds a permit, potentially + # releasing a blocking acquirer. + # However, no actual permit objects are used; the Semaphore just keeps a + # count of the number available and acts accordingly. + # Alternatively, permits may be acquired within a block, and automatically + # released after the block finishes executing. + # + # @!macro semaphore_public_api + # @example + # semaphore = Concurrent::Semaphore.new(2) + # + # t1 = Thread.new do + # semaphore.acquire + # puts "Thread 1 acquired semaphore" + # end + # + # t2 = Thread.new do + # semaphore.acquire + # puts "Thread 2 acquired semaphore" + # end + # + # t3 = Thread.new do + # semaphore.acquire + # puts "Thread 3 acquired semaphore" + # end + # + # t4 = Thread.new do + # sleep(2) + # puts "Thread 4 releasing semaphore" + # semaphore.release + # end + # + # [t1, t2, t3, t4].each(&:join) + # + # # prints: + # # Thread 3 acquired semaphore + # # Thread 2 acquired semaphore + # # Thread 4 releasing semaphore + # # Thread 1 acquired semaphore + # + # @example + # semaphore = Concurrent::Semaphore.new(1) + # + # puts semaphore.available_permits + # semaphore.acquire do + # puts semaphore.available_permits + # end + # puts semaphore.available_permits + # + # # prints: + # # 1 + # # 0 + # # 1 + class Semaphore < SemaphoreImplementation + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb new file mode 100644 index 0000000000000..3b7e12b5bb97c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb @@ -0,0 +1,111 @@ +require 'concurrent/constants' +require_relative 'locals' + +module Concurrent + + # A `ThreadLocalVar` is a variable where the value is different for each thread. + # Each variable may have a default value, but when you modify the variable only + # the current thread will ever see that change. + # + # This is similar to Ruby's built-in thread-local variables (`Thread#thread_variable_get`), + # but with these major advantages: + # * `ThreadLocalVar` has its own identity, it doesn't need a Symbol. + # * Each Ruby's built-in thread-local variable leaks some memory forever (it's a Symbol held forever on the thread), + # so it's only OK to create a small amount of them. + # `ThreadLocalVar` has no such issue and it is fine to create many of them. + # * Ruby's built-in thread-local variables leak forever the value set on each thread (unless set to nil explicitly). + # `ThreadLocalVar` automatically removes the mapping for each thread once the `ThreadLocalVar` instance is GC'd. + # + # @!macro thread_safe_variable_comparison + # + # @example + # v = ThreadLocalVar.new(14) + # v.value #=> 14 + # v.value = 2 + # v.value #=> 2 + # + # @example + # v = ThreadLocalVar.new(14) + # + # t1 = Thread.new do + # v.value #=> 14 + # v.value = 1 + # v.value #=> 1 + # end + # + # t2 = Thread.new do + # v.value #=> 14 + # v.value = 2 + # v.value #=> 2 + # end + # + # v.value #=> 14 + class ThreadLocalVar + LOCALS = ThreadLocals.new + + # Creates a thread local variable. + # + # @param [Object] default the default value when otherwise unset + # @param [Proc] default_block Optional block that gets called to obtain the + # default value for each thread + def initialize(default = nil, &default_block) + if default && block_given? + raise ArgumentError, "Cannot use both value and block as default value" + end + + if block_given? + @default_block = default_block + @default = nil + else + @default_block = nil + @default = default + end + + @index = LOCALS.next_index(self) + end + + # Returns the value in the current thread's copy of this thread-local variable. + # + # @return [Object] the current value + def value + LOCALS.fetch(@index) { default } + end + + # Sets the current thread's copy of this thread-local variable to the specified value. + # + # @param [Object] value the value to set + # @return [Object] the new value + def value=(value) + LOCALS.set(@index, value) + end + + # Bind the given value to thread local storage during + # execution of the given block. + # + # @param [Object] value the value to bind + # @yield the operation to be performed with the bound variable + # @return [Object] the value + def bind(value) + if block_given? + old_value = self.value + self.value = value + begin + yield + ensure + self.value = old_value + end + end + end + + protected + + # @!visibility private + def default + if @default_block + self.value = @default_block.call + else + @default + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb new file mode 100644 index 0000000000000..5d2d7edd4f540 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb @@ -0,0 +1,37 @@ +require 'concurrent/errors' + +module Concurrent + + # Define update methods that use direct paths + # + # @!visibility private + # @!macro internal_implementation_note + module AtomicDirectUpdate + def update + true until compare_and_set(old_value = get, new_value = yield(old_value)) + new_value + end + + def try_update + old_value = get + new_value = yield old_value + + return unless compare_and_set old_value, new_value + + new_value + end + + def try_update! + old_value = get + new_value = yield old_value + unless compare_and_set(old_value, new_value) + if $VERBOSE + raise ConcurrentUpdateError, "Update failed" + else + raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE + end + end + new_value + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb new file mode 100644 index 0000000000000..e5e2a6377d59a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb @@ -0,0 +1,67 @@ +require 'concurrent/atomic_reference/atomic_direct_update' +require 'concurrent/atomic_reference/numeric_cas_wrapper' +require 'concurrent/synchronization/safe_initialization' + +module Concurrent + + # @!visibility private + # @!macro internal_implementation_note + class MutexAtomicReference + extend Concurrent::Synchronization::SafeInitialization + include AtomicDirectUpdate + include AtomicNumericCompareAndSetWrapper + alias_method :compare_and_swap, :compare_and_set + + # @!macro atomic_reference_method_initialize + def initialize(value = nil) + super() + @Lock = ::Mutex.new + @value = value + end + + # @!macro atomic_reference_method_get + def get + synchronize { @value } + end + alias_method :value, :get + + # @!macro atomic_reference_method_set + def set(new_value) + synchronize { @value = new_value } + end + alias_method :value=, :set + + # @!macro atomic_reference_method_get_and_set + def get_and_set(new_value) + synchronize do + old_value = @value + @value = new_value + old_value + end + end + alias_method :swap, :get_and_set + + # @!macro atomic_reference_method_compare_and_set + def _compare_and_set(old_value, new_value) + synchronize do + if @value.equal? old_value + @value = new_value + true + else + false + end + end + end + + protected + + # @!visibility private + def synchronize + if @Lock.owned? + yield + else + @Lock.synchronize { yield } + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb new file mode 100644 index 0000000000000..709a3822318dc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb @@ -0,0 +1,28 @@ +module Concurrent + + # Special "compare and set" handling of numeric values. + # + # @!visibility private + # @!macro internal_implementation_note + module AtomicNumericCompareAndSetWrapper + + # @!macro atomic_reference_method_compare_and_set + def compare_and_set(old_value, new_value) + if old_value.kind_of? Numeric + while true + old = get + + return false unless old.kind_of? Numeric + + return false unless old == old_value + + result = _compare_and_set(old, new_value) + return result if result + end + else + _compare_and_set(old_value, new_value) + end + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomics.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomics.rb new file mode 100644 index 0000000000000..16cbe66101b1e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/atomics.rb @@ -0,0 +1,10 @@ +require 'concurrent/atomic/atomic_reference' +require 'concurrent/atomic/atomic_boolean' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/atomic/cyclic_barrier' +require 'concurrent/atomic/count_down_latch' +require 'concurrent/atomic/event' +require 'concurrent/atomic/read_write_lock' +require 'concurrent/atomic/reentrant_read_write_lock' +require 'concurrent/atomic/semaphore' +require 'concurrent/atomic/thread_local_var' diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb new file mode 100644 index 0000000000000..7c700bd78ac4c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb @@ -0,0 +1,107 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + module Collection + + # A thread safe observer set implemented using copy-on-read approach: + # observers are added and removed from a thread safe collection; every time + # a notification is required the internal data structure is copied to + # prevent concurrency issues + # + # @api private + class CopyOnNotifyObserverSet < Synchronization::LockableObject + + def initialize + super() + synchronize { ns_initialize } + end + + # @!macro observable_add_observer + def add_observer(observer = nil, func = :update, &block) + if observer.nil? && block.nil? + raise ArgumentError, 'should pass observer as a first argument or block' + elsif observer && block + raise ArgumentError.new('cannot provide both an observer and a block') + end + + if block + observer = block + func = :call + end + + synchronize do + @observers[observer] = func + observer + end + end + + # @!macro observable_delete_observer + def delete_observer(observer) + synchronize do + @observers.delete(observer) + observer + end + end + + # @!macro observable_delete_observers + def delete_observers + synchronize do + @observers.clear + self + end + end + + # @!macro observable_count_observers + def count_observers + synchronize { @observers.count } + end + + # Notifies all registered observers with optional args + # @param [Object] args arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + def notify_observers(*args, &block) + observers = duplicate_observers + notify_to(observers, *args, &block) + self + end + + # Notifies all registered observers with optional args and deletes them. + # + # @param [Object] args arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + def notify_and_delete_observers(*args, &block) + observers = duplicate_and_clear_observers + notify_to(observers, *args, &block) + self + end + + protected + + def ns_initialize + @observers = {} + end + + private + + def duplicate_and_clear_observers + synchronize do + observers = @observers.dup + @observers.clear + observers + end + end + + def duplicate_observers + synchronize { @observers.dup } + end + + def notify_to(observers, *args) + raise ArgumentError.new('cannot give arguments and a block') if block_given? && !args.empty? + observers.each do |observer, function| + args = yield if block_given? + observer.send(function, *args) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb new file mode 100644 index 0000000000000..bcb6750d41109 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb @@ -0,0 +1,111 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + module Collection + + # A thread safe observer set implemented using copy-on-write approach: + # every time an observer is added or removed the whole internal data structure is + # duplicated and replaced with a new one. + # + # @api private + class CopyOnWriteObserverSet < Synchronization::LockableObject + + def initialize + super() + synchronize { ns_initialize } + end + + # @!macro observable_add_observer + def add_observer(observer = nil, func = :update, &block) + if observer.nil? && block.nil? + raise ArgumentError, 'should pass observer as a first argument or block' + elsif observer && block + raise ArgumentError.new('cannot provide both an observer and a block') + end + + if block + observer = block + func = :call + end + + synchronize do + new_observers = @observers.dup + new_observers[observer] = func + @observers = new_observers + observer + end + end + + # @!macro observable_delete_observer + def delete_observer(observer) + synchronize do + new_observers = @observers.dup + new_observers.delete(observer) + @observers = new_observers + observer + end + end + + # @!macro observable_delete_observers + def delete_observers + self.observers = {} + self + end + + # @!macro observable_count_observers + def count_observers + observers.count + end + + # Notifies all registered observers with optional args + # @param [Object] args arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + def notify_observers(*args, &block) + notify_to(observers, *args, &block) + self + end + + # Notifies all registered observers with optional args and deletes them. + # + # @param [Object] args arguments to be passed to each observer + # @return [CopyOnWriteObserverSet] self + def notify_and_delete_observers(*args, &block) + old = clear_observers_and_return_old + notify_to(old, *args, &block) + self + end + + protected + + def ns_initialize + @observers = {} + end + + private + + def notify_to(observers, *args) + raise ArgumentError.new('cannot give arguments and a block') if block_given? && !args.empty? + observers.each do |observer, function| + args = yield if block_given? + observer.send(function, *args) + end + end + + def observers + synchronize { @observers } + end + + def observers=(new_set) + synchronize { @observers = new_set } + end + + def clear_observers_and_return_old + synchronize do + old_observers = @observers + @observers = {} + old_observers + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb new file mode 100644 index 0000000000000..2be9e4373a32d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb @@ -0,0 +1,84 @@ +if Concurrent.on_jruby? + + module Concurrent + module Collection + + + # @!macro priority_queue + # + # @!visibility private + # @!macro internal_implementation_note + class JavaNonConcurrentPriorityQueue + + # @!macro priority_queue_method_initialize + def initialize(opts = {}) + order = opts.fetch(:order, :max) + if [:min, :low].include?(order) + @queue = java.util.PriorityQueue.new(11) # 11 is the default initial capacity + else + @queue = java.util.PriorityQueue.new(11, java.util.Collections.reverseOrder()) + end + end + + # @!macro priority_queue_method_clear + def clear + @queue.clear + true + end + + # @!macro priority_queue_method_delete + def delete(item) + found = false + while @queue.remove(item) do + found = true + end + found + end + + # @!macro priority_queue_method_empty + def empty? + @queue.size == 0 + end + + # @!macro priority_queue_method_include + def include?(item) + @queue.contains(item) + end + alias_method :has_priority?, :include? + + # @!macro priority_queue_method_length + def length + @queue.size + end + alias_method :size, :length + + # @!macro priority_queue_method_peek + def peek + @queue.peek + end + + # @!macro priority_queue_method_pop + def pop + @queue.poll + end + alias_method :deq, :pop + alias_method :shift, :pop + + # @!macro priority_queue_method_push + def push(item) + raise ArgumentError.new('cannot enqueue nil') if item.nil? + @queue.add(item) + end + alias_method :<<, :push + alias_method :enq, :push + + # @!macro priority_queue_method_from_list + def self.from_list(list, opts = {}) + queue = new(opts) + list.each{|item| queue << item } + queue + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb new file mode 100644 index 0000000000000..3704410ba0bd4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb @@ -0,0 +1,160 @@ +require 'concurrent/synchronization/object' + +module Concurrent + + # @!macro warn.edge + class LockFreeStack < Synchronization::Object + + safe_initialization! + + class Node + # TODO (pitr-ch 20-Dec-2016): Could be unified with Stack class? + + # @return [Node] + attr_reader :next_node + + # @return [Object] + attr_reader :value + + # @!visibility private + # allow to nil-ify to free GC when the entry is no longer relevant, not synchronised + attr_writer :value + + def initialize(value, next_node) + @value = value + @next_node = next_node + end + + singleton_class.send :alias_method, :[], :new + end + + # The singleton for empty node + EMPTY = Node[nil, nil] + def EMPTY.next_node + self + end + + attr_atomic(:head) + private :head, :head=, :swap_head, :compare_and_set_head, :update_head + + # @!visibility private + def self.of1(value) + new Node[value, EMPTY] + end + + # @!visibility private + def self.of2(value1, value2) + new Node[value1, Node[value2, EMPTY]] + end + + # @param [Node] head + def initialize(head = EMPTY) + super() + self.head = head + end + + # @param [Node] head + # @return [true, false] + def empty?(head = head()) + head.equal? EMPTY + end + + # @param [Node] head + # @param [Object] value + # @return [true, false] + def compare_and_push(head, value) + compare_and_set_head head, Node[value, head] + end + + # @param [Object] value + # @return [self] + def push(value) + while true + current_head = head + return self if compare_and_set_head current_head, Node[value, current_head] + end + end + + # @return [Node] + def peek + head + end + + # @param [Node] head + # @return [true, false] + def compare_and_pop(head) + compare_and_set_head head, head.next_node + end + + # @return [Object] + def pop + while true + current_head = head + return current_head.value if compare_and_set_head current_head, current_head.next_node + end + end + + # @param [Node] head + # @return [true, false] + def compare_and_clear(head) + compare_and_set_head head, EMPTY + end + + include Enumerable + + # @param [Node] head + # @return [self] + def each(head = nil) + return to_enum(:each, head) unless block_given? + it = head || peek + until it.equal?(EMPTY) + yield it.value + it = it.next_node + end + self + end + + # @return [true, false] + def clear + while true + current_head = head + return false if current_head == EMPTY + return true if compare_and_set_head current_head, EMPTY + end + end + + # @param [Node] head + # @return [true, false] + def clear_if(head) + compare_and_set_head head, EMPTY + end + + # @param [Node] head + # @param [Node] new_head + # @return [true, false] + def replace_if(head, new_head) + compare_and_set_head head, new_head + end + + # @return [self] + # @yield over the cleared stack + # @yieldparam [Object] value + def clear_each(&block) + while true + current_head = head + return self if current_head == EMPTY + if compare_and_set_head current_head, EMPTY + each current_head, &block + return self + end + end + end + + # @return [String] Short string representation. + def to_s + format '%s %s>', super[0..-2], to_a.to_s + end + + alias_method :inspect, :to_s + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb new file mode 100644 index 0000000000000..e0cf9990c52e0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb @@ -0,0 +1,66 @@ +require 'thread' +require 'concurrent/collection/map/non_concurrent_map_backend' + +module Concurrent + + # @!visibility private + module Collection + + # @!visibility private + class MriMapBackend < NonConcurrentMapBackend + + def initialize(options = nil, &default_proc) + super(options, &default_proc) + @write_lock = Mutex.new + end + + def []=(key, value) + @write_lock.synchronize { super } + end + + def compute_if_absent(key) + if NULL != (stored_value = @backend.fetch(key, NULL)) # fast non-blocking path for the most likely case + stored_value + else + @write_lock.synchronize { super } + end + end + + def compute_if_present(key) + @write_lock.synchronize { super } + end + + def compute(key) + @write_lock.synchronize { super } + end + + def merge_pair(key, value) + @write_lock.synchronize { super } + end + + def replace_pair(key, old_value, new_value) + @write_lock.synchronize { super } + end + + def replace_if_exists(key, new_value) + @write_lock.synchronize { super } + end + + def get_and_set(key, value) + @write_lock.synchronize { super } + end + + def delete(key) + @write_lock.synchronize { super } + end + + def delete_pair(key, value) + @write_lock.synchronize { super } + end + + def clear + @write_lock.synchronize { super } + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb new file mode 100644 index 0000000000000..ca5fd9b48e37b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb @@ -0,0 +1,148 @@ +require 'concurrent/constants' + +module Concurrent + + # @!visibility private + module Collection + + # @!visibility private + class NonConcurrentMapBackend + + # WARNING: all public methods of the class must operate on the @backend + # directly without calling each other. This is important because of the + # SynchronizedMapBackend which uses a non-reentrant mutex for performance + # reasons. + def initialize(options = nil, &default_proc) + validate_options_hash!(options) if options.kind_of?(::Hash) + set_backend(default_proc) + @default_proc = default_proc + end + + def [](key) + @backend[key] + end + + def []=(key, value) + @backend[key] = value + end + + def compute_if_absent(key) + if NULL != (stored_value = @backend.fetch(key, NULL)) + stored_value + else + @backend[key] = yield + end + end + + def replace_pair(key, old_value, new_value) + if pair?(key, old_value) + @backend[key] = new_value + true + else + false + end + end + + def replace_if_exists(key, new_value) + if NULL != (stored_value = @backend.fetch(key, NULL)) + @backend[key] = new_value + stored_value + end + end + + def compute_if_present(key) + if NULL != (stored_value = @backend.fetch(key, NULL)) + store_computed_value(key, yield(stored_value)) + end + end + + def compute(key) + store_computed_value(key, yield(get_or_default(key, nil))) + end + + def merge_pair(key, value) + if NULL == (stored_value = @backend.fetch(key, NULL)) + @backend[key] = value + else + store_computed_value(key, yield(stored_value)) + end + end + + def get_and_set(key, value) + stored_value = get_or_default(key, nil) + @backend[key] = value + stored_value + end + + def key?(key) + @backend.key?(key) + end + + def delete(key) + @backend.delete(key) + end + + def delete_pair(key, value) + if pair?(key, value) + @backend.delete(key) + true + else + false + end + end + + def clear + @backend.clear + self + end + + def each_pair + dupped_backend.each_pair do |k, v| + yield k, v + end + self + end + + def size + @backend.size + end + + def get_or_default(key, default_value) + @backend.fetch(key, default_value) + end + + private + + def set_backend(default_proc) + if default_proc + @backend = ::Hash.new { |_h, key| default_proc.call(self, key) } + else + @backend = {} + end + end + + def initialize_copy(other) + super + set_backend(@default_proc) + self + end + + def dupped_backend + @backend.dup + end + + def pair?(key, expected_value) + NULL != (stored_value = @backend.fetch(key, NULL)) && expected_value.equal?(stored_value) + end + + def store_computed_value(key, new_value) + if new_value.nil? + @backend.delete(key) + nil + else + @backend[key] = new_value + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb new file mode 100644 index 0000000000000..efa161ed9eaa6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb @@ -0,0 +1,85 @@ +require 'concurrent/collection/map/non_concurrent_map_backend' + +module Concurrent + + # @!visibility private + module Collection + + # @!visibility private + class SynchronizedMapBackend < NonConcurrentMapBackend + + def initialize(*args, &block) + super + + # WARNING: Mutex is a non-reentrant lock, so the synchronized methods are + # not allowed to call each other. + @mutex = Mutex.new + end + + def [](key) + @mutex.synchronize { super } + end + + def []=(key, value) + @mutex.synchronize { super } + end + + def compute_if_absent(key) + @mutex.synchronize { super } + end + + def compute_if_present(key) + @mutex.synchronize { super } + end + + def compute(key) + @mutex.synchronize { super } + end + + def merge_pair(key, value) + @mutex.synchronize { super } + end + + def replace_pair(key, old_value, new_value) + @mutex.synchronize { super } + end + + def replace_if_exists(key, new_value) + @mutex.synchronize { super } + end + + def get_and_set(key, value) + @mutex.synchronize { super } + end + + def key?(key) + @mutex.synchronize { super } + end + + def delete(key) + @mutex.synchronize { super } + end + + def delete_pair(key, value) + @mutex.synchronize { super } + end + + def clear + @mutex.synchronize { super } + end + + def size + @mutex.synchronize { super } + end + + def get_or_default(key, default_value) + @mutex.synchronize { super } + end + + private + def dupped_backend + @mutex.synchronize { super } + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb new file mode 100644 index 0000000000000..68a1b3884df10 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb @@ -0,0 +1,14 @@ +module Concurrent + + # @!visibility private + module Collection + + # @!visibility private + class TruffleRubyMapBackend < TruffleRuby::ConcurrentMap + def initialize(options = nil) + options ||= {} + super(initial_capacity: options[:initial_capacity], load_factor: options[:load_factor]) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb new file mode 100644 index 0000000000000..694cd7ac7cdec --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb @@ -0,0 +1,143 @@ +require 'concurrent/utility/engine' +require 'concurrent/collection/java_non_concurrent_priority_queue' +require 'concurrent/collection/ruby_non_concurrent_priority_queue' + +module Concurrent + module Collection + + # @!visibility private + # @!macro internal_implementation_note + NonConcurrentPriorityQueueImplementation = case + when Concurrent.on_jruby? + JavaNonConcurrentPriorityQueue + else + RubyNonConcurrentPriorityQueue + end + private_constant :NonConcurrentPriorityQueueImplementation + + # @!macro priority_queue + # + # A queue collection in which the elements are sorted based on their + # comparison (spaceship) operator `<=>`. Items are added to the queue + # at a position relative to their priority. On removal the element + # with the "highest" priority is removed. By default the sort order is + # from highest to lowest, but a lowest-to-highest sort order can be + # set on construction. + # + # The API is based on the `Queue` class from the Ruby standard library. + # + # The pure Ruby implementation, `RubyNonConcurrentPriorityQueue` uses a heap algorithm + # stored in an array. The algorithm is based on the work of Robert Sedgewick + # and Kevin Wayne. + # + # The JRuby native implementation is a thin wrapper around the standard + # library `java.util.NonConcurrentPriorityQueue`. + # + # When running under JRuby the class `NonConcurrentPriorityQueue` extends `JavaNonConcurrentPriorityQueue`. + # When running under all other interpreters it extends `RubyNonConcurrentPriorityQueue`. + # + # @note This implementation is *not* thread safe. + # + # @see http://en.wikipedia.org/wiki/Priority_queue + # @see http://ruby-doc.org/stdlib-2.0.0/libdoc/thread/rdoc/Queue.html + # + # @see http://algs4.cs.princeton.edu/24pq/index.php#2.6 + # @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html + # + # @!visibility private + class NonConcurrentPriorityQueue < NonConcurrentPriorityQueueImplementation + + alias_method :has_priority?, :include? + + alias_method :size, :length + + alias_method :deq, :pop + alias_method :shift, :pop + + alias_method :<<, :push + alias_method :enq, :push + + # @!method initialize(opts = {}) + # @!macro priority_queue_method_initialize + # + # Create a new priority queue with no items. + # + # @param [Hash] opts the options for creating the queue + # @option opts [Symbol] :order (:max) dictates the order in which items are + # stored: from highest to lowest when `:max` or `:high`; from lowest to + # highest when `:min` or `:low` + + # @!method clear + # @!macro priority_queue_method_clear + # + # Removes all of the elements from this priority queue. + + # @!method delete(item) + # @!macro priority_queue_method_delete + # + # Deletes all items from `self` that are equal to `item`. + # + # @param [Object] item the item to be removed from the queue + # @return [Object] true if the item is found else false + + # @!method empty? + # @!macro priority_queue_method_empty + # + # Returns `true` if `self` contains no elements. + # + # @return [Boolean] true if there are no items in the queue else false + + # @!method include?(item) + # @!macro priority_queue_method_include + # + # Returns `true` if the given item is present in `self` (that is, if any + # element == `item`), otherwise returns false. + # + # @param [Object] item the item to search for + # + # @return [Boolean] true if the item is found else false + + # @!method length + # @!macro priority_queue_method_length + # + # The current length of the queue. + # + # @return [Fixnum] the number of items in the queue + + # @!method peek + # @!macro priority_queue_method_peek + # + # Retrieves, but does not remove, the head of this queue, or returns `nil` + # if this queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + + # @!method pop + # @!macro priority_queue_method_pop + # + # Retrieves and removes the head of this queue, or returns `nil` if this + # queue is empty. + # + # @return [Object] the head of the queue or `nil` when empty + + # @!method push(item) + # @!macro priority_queue_method_push + # + # Inserts the specified element into this priority queue. + # + # @param [Object] item the item to insert onto the queue + + # @!method self.from_list(list, opts = {}) + # @!macro priority_queue_method_from_list + # + # Create a new priority queue from the given list. + # + # @param [Enumerable] list the list to build the queue from + # @param [Hash] opts the options for creating the queue + # + # @return [NonConcurrentPriorityQueue] the newly created and populated queue + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb new file mode 100644 index 0000000000000..322b4ac2d95ae --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb @@ -0,0 +1,160 @@ +module Concurrent + module Collection + + # @!macro priority_queue + # + # @!visibility private + # @!macro internal_implementation_note + class RubyNonConcurrentPriorityQueue + + # @!macro priority_queue_method_initialize + def initialize(opts = {}) + order = opts.fetch(:order, :max) + @comparator = [:min, :low].include?(order) ? -1 : 1 + clear + end + + # @!macro priority_queue_method_clear + def clear + @queue = [nil] + @length = 0 + true + end + + # @!macro priority_queue_method_delete + def delete(item) + return false if empty? + original_length = @length + k = 1 + while k <= @length + if @queue[k] == item + swap(k, @length) + @length -= 1 + sink(k) || swim(k) + @queue.pop + else + k += 1 + end + end + @length != original_length + end + + # @!macro priority_queue_method_empty + def empty? + size == 0 + end + + # @!macro priority_queue_method_include + def include?(item) + @queue.include?(item) + end + alias_method :has_priority?, :include? + + # @!macro priority_queue_method_length + def length + @length + end + alias_method :size, :length + + # @!macro priority_queue_method_peek + def peek + empty? ? nil : @queue[1] + end + + # @!macro priority_queue_method_pop + def pop + return nil if empty? + max = @queue[1] + swap(1, @length) + @length -= 1 + sink(1) + @queue.pop + max + end + alias_method :deq, :pop + alias_method :shift, :pop + + # @!macro priority_queue_method_push + def push(item) + raise ArgumentError.new('cannot enqueue nil') if item.nil? + @length += 1 + @queue << item + swim(@length) + true + end + alias_method :<<, :push + alias_method :enq, :push + + # @!macro priority_queue_method_from_list + def self.from_list(list, opts = {}) + queue = new(opts) + list.each{|item| queue << item } + queue + end + + private + + # Exchange the values at the given indexes within the internal array. + # + # @param [Integer] x the first index to swap + # @param [Integer] y the second index to swap + # + # @!visibility private + def swap(x, y) + temp = @queue[x] + @queue[x] = @queue[y] + @queue[y] = temp + end + + # Are the items at the given indexes ordered based on the priority + # order specified at construction? + # + # @param [Integer] x the first index from which to retrieve a comparable value + # @param [Integer] y the second index from which to retrieve a comparable value + # + # @return [Boolean] true if the two elements are in the correct priority order + # else false + # + # @!visibility private + def ordered?(x, y) + (@queue[x] <=> @queue[y]) == @comparator + end + + # Percolate down to maintain heap invariant. + # + # @param [Integer] k the index at which to start the percolation + # + # @!visibility private + def sink(k) + success = false + + while (j = (2 * k)) <= @length do + j += 1 if j < @length && ! ordered?(j, j+1) + break if ordered?(k, j) + swap(k, j) + success = true + k = j + end + + success + end + + # Percolate up to maintain heap invariant. + # + # @param [Integer] k the index at which to start the percolation + # + # @!visibility private + def swim(k) + success = false + + while k > 1 && ! ordered?(k/2, k) do + swap(k, k/2) + k = k/2 + success = true + end + + success + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/deprecation.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/deprecation.rb new file mode 100644 index 0000000000000..35ae4b2c9df68 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/deprecation.rb @@ -0,0 +1,34 @@ +require 'concurrent/concern/logging' + +module Concurrent + module Concern + + # @!visibility private + # @!macro internal_implementation_note + module Deprecation + # TODO require additional parameter: a version. Display when it'll be removed based on that. Error if not removed. + include Concern::Logging + + def deprecated(message, strip = 2) + caller_line = caller(strip).first if strip > 0 + klass = if Module === self + self + else + self.class + end + message = if strip > 0 + format("[DEPRECATED] %s\ncalled on: %s", message, caller_line) + else + format('[DEPRECATED] %s', message) + end + log WARN, klass.to_s, message + end + + def deprecated_method(old_name, new_name) + deprecated "`#{old_name}` is deprecated and it'll removed in next release, use `#{new_name}` instead", 3 + end + + extend self + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb new file mode 100644 index 0000000000000..dc172ba74d93d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb @@ -0,0 +1,73 @@ +module Concurrent + module Concern + + # Object references in Ruby are mutable. This can lead to serious problems when + # the `#value` of a concurrent object is a mutable reference. Which is always the + # case unless the value is a `Fixnum`, `Symbol`, or similar "primitive" data type. + # Most classes in this library that expose a `#value` getter method do so using the + # `Dereferenceable` mixin module. + # + # @!macro copy_options + module Dereferenceable + # NOTE: This module is going away in 2.0. In the mean time we need it to + # play nicely with the synchronization layer. This means that the + # including class SHOULD be synchronized and it MUST implement a + # `#synchronize` method. Not doing so will lead to runtime errors. + + # Return the value this object represents after applying the options specified + # by the `#set_deref_options` method. + # + # @return [Object] the current value of the object + def value + synchronize { apply_deref_options(@value) } + end + alias_method :deref, :value + + protected + + # Set the internal value of this object + # + # @param [Object] value the new value + def value=(value) + synchronize{ @value = value } + end + + # @!macro dereferenceable_set_deref_options + # Set the options which define the operations #value performs before + # returning data to the caller (dereferencing). + # + # @note Most classes that include this module will call `#set_deref_options` + # from within the constructor, thus allowing these options to be set at + # object creation. + # + # @param [Hash] opts the options defining dereference behavior. + # @option opts [String] :dup_on_deref (false) call `#dup` before returning the data + # @option opts [String] :freeze_on_deref (false) call `#freeze` before returning the data + # @option opts [String] :copy_on_deref (nil) call the given `Proc` passing + # the internal value and returning the value returned from the proc + def set_deref_options(opts = {}) + synchronize{ ns_set_deref_options(opts) } + end + + # @!macro dereferenceable_set_deref_options + # @!visibility private + def ns_set_deref_options(opts) + @dup_on_deref = opts[:dup_on_deref] || opts[:dup] + @freeze_on_deref = opts[:freeze_on_deref] || opts[:freeze] + @copy_on_deref = opts[:copy_on_deref] || opts[:copy] + @do_nothing_on_deref = !(@dup_on_deref || @freeze_on_deref || @copy_on_deref) + nil + end + + # @!visibility private + def apply_deref_options(value) + return nil if value.nil? + return value if @do_nothing_on_deref + value = @copy_on_deref.call(value) if @copy_on_deref + value = value.dup if @dup_on_deref + value = value.freeze if @freeze_on_deref + value + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/logging.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/logging.rb new file mode 100644 index 0000000000000..568a539ebf0b8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/logging.rb @@ -0,0 +1,116 @@ +require 'logger' +require 'concurrent/atomic/atomic_reference' + +module Concurrent + module Concern + + # Include where logging is needed + # + # @!visibility private + module Logging + include Logger::Severity + + # Logs through {Concurrent.global_logger}, it can be overridden by setting @logger + # @param [Integer] level one of Logger::Severity constants + # @param [String] progname e.g. a path of an Actor + # @param [String, nil] message when nil block is used to generate the message + # @yieldreturn [String] a message + def log(level, progname, message = nil, &block) + logger = if defined?(@logger) && @logger + @logger + else + Concurrent.global_logger + end + logger.call level, progname, message, &block + rescue => error + $stderr.puts "`Concurrent.configuration.logger` failed to log #{[level, progname, message, block]}\n" + + "#{error.message} (#{error.class})\n#{error.backtrace.join "\n"}" + end + end + end +end + +module Concurrent + extend Concern::Logging + + # @return [Logger] Logger with provided level and output. + def self.create_simple_logger(level = Logger::FATAL, output = $stderr) + # TODO (pitr-ch 24-Dec-2016): figure out why it had to be replaced, stdlogger was deadlocking + lambda do |severity, progname, message = nil, &block| + return false if severity < level + + message = block ? block.call : message + formatted_message = case message + when String + message + when Exception + format "%s (%s)\n%s", + message.message, message.class, (message.backtrace || []).join("\n") + else + message.inspect + end + + output.print format "[%s] %5s -- %s: %s\n", + Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'), + Logger::SEV_LABEL[severity], + progname, + formatted_message + true + end + end + + # Use logger created by #create_simple_logger to log concurrent-ruby messages. + def self.use_simple_logger(level = Logger::FATAL, output = $stderr) + Concurrent.global_logger = create_simple_logger level, output + end + + # @return [Logger] Logger with provided level and output. + # @deprecated + def self.create_stdlib_logger(level = Logger::FATAL, output = $stderr) + logger = Logger.new(output) + logger.level = level + logger.formatter = lambda do |severity, datetime, progname, msg| + formatted_message = case msg + when String + msg + when Exception + format "%s (%s)\n%s", + msg.message, msg.class, (msg.backtrace || []).join("\n") + else + msg.inspect + end + format "[%s] %5s -- %s: %s\n", + datetime.strftime('%Y-%m-%d %H:%M:%S.%L'), + severity, + progname, + formatted_message + end + + lambda do |loglevel, progname, message = nil, &block| + logger.add loglevel, message, progname, &block + end + end + + # Use logger created by #create_stdlib_logger to log concurrent-ruby messages. + # @deprecated + def self.use_stdlib_logger(level = Logger::FATAL, output = $stderr) + Concurrent.global_logger = create_stdlib_logger level, output + end + + # TODO (pitr-ch 27-Dec-2016): remove deadlocking stdlib_logger methods + + # Suppresses all output when used for logging. + NULL_LOGGER = lambda { |level, progname, message = nil, &block| } + + # @!visibility private + GLOBAL_LOGGER = AtomicReference.new(create_simple_logger(Logger::WARN)) + private_constant :GLOBAL_LOGGER + + def self.global_logger + GLOBAL_LOGGER.value + end + + def self.global_logger=(value) + GLOBAL_LOGGER.value = value + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/obligation.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/obligation.rb new file mode 100644 index 0000000000000..2c9ac12003502 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/obligation.rb @@ -0,0 +1,220 @@ +require 'thread' +require 'timeout' + +require 'concurrent/atomic/event' +require 'concurrent/concern/dereferenceable' + +module Concurrent + module Concern + + module Obligation + include Concern::Dereferenceable + # NOTE: The Dereferenceable module is going away in 2.0. In the mean time + # we need it to place nicely with the synchronization layer. This means + # that the including class SHOULD be synchronized and it MUST implement a + # `#synchronize` method. Not doing so will lead to runtime errors. + + # Has the obligation been fulfilled? + # + # @return [Boolean] + def fulfilled? + state == :fulfilled + end + alias_method :realized?, :fulfilled? + + # Has the obligation been rejected? + # + # @return [Boolean] + def rejected? + state == :rejected + end + + # Is obligation completion still pending? + # + # @return [Boolean] + def pending? + state == :pending + end + + # Is the obligation still unscheduled? + # + # @return [Boolean] + def unscheduled? + state == :unscheduled + end + + # Has the obligation completed processing? + # + # @return [Boolean] + def complete? + [:fulfilled, :rejected].include? state + end + + # Is the obligation still awaiting completion of processing? + # + # @return [Boolean] + def incomplete? + ! complete? + end + + # The current value of the obligation. Will be `nil` while the state is + # pending or the operation has been rejected. + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Object] see Dereferenceable#deref + def value(timeout = nil) + wait timeout + deref + end + + # Wait until obligation is complete or the timeout has been reached. + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Obligation] self + def wait(timeout = nil) + event.wait(timeout) if timeout != 0 && incomplete? + self + end + + # Wait until obligation is complete or the timeout is reached. Will re-raise + # any exceptions raised during processing (but will not raise an exception + # on timeout). + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Obligation] self + # @raise [Exception] raises the reason when rejected + def wait!(timeout = nil) + wait(timeout).tap { raise self if rejected? } + end + alias_method :no_error!, :wait! + + # The current value of the obligation. Will be `nil` while the state is + # pending or the operation has been rejected. Will re-raise any exceptions + # raised during processing (but will not raise an exception on timeout). + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Object] see Dereferenceable#deref + # @raise [Exception] raises the reason when rejected + def value!(timeout = nil) + wait(timeout) + if rejected? + raise self + else + deref + end + end + + # The current state of the obligation. + # + # @return [Symbol] the current state + def state + synchronize { @state } + end + + # If an exception was raised during processing this will return the + # exception object. Will return `nil` when the state is pending or if + # the obligation has been successfully fulfilled. + # + # @return [Exception] the exception raised during processing or `nil` + def reason + synchronize { @reason } + end + + # @example allows Obligation to be risen + # rejected_ivar = Ivar.new.fail + # raise rejected_ivar + def exception(*args) + raise 'obligation is not rejected' unless rejected? + reason.exception(*args) + end + + protected + + # @!visibility private + def get_arguments_from(opts = {}) + [*opts.fetch(:args, [])] + end + + # @!visibility private + def init_obligation + @event = Event.new + @value = @reason = nil + end + + # @!visibility private + def event + @event + end + + # @!visibility private + def set_state(success, value, reason) + if success + @value = value + @state = :fulfilled + else + @reason = reason + @state = :rejected + end + end + + # @!visibility private + def state=(value) + synchronize { ns_set_state(value) } + end + + # Atomic compare and set operation + # State is set to `next_state` only if `current state == expected_current`. + # + # @param [Symbol] next_state + # @param [Symbol] expected_current + # + # @return [Boolean] true is state is changed, false otherwise + # + # @!visibility private + def compare_and_set_state(next_state, *expected_current) + synchronize do + if expected_current.include? @state + @state = next_state + true + else + false + end + end + end + + # Executes the block within mutex if current state is included in expected_states + # + # @return block value if executed, false otherwise + # + # @!visibility private + def if_state(*expected_states) + synchronize do + raise ArgumentError.new('no block given') unless block_given? + + if expected_states.include? @state + yield + else + false + end + end + end + + protected + + # Am I in the current state? + # + # @param [Symbol] expected The state to check against + # @return [Boolean] true if in the expected state else false + # + # @!visibility private + def ns_check_state?(expected) + @state == expected + end + + # @!visibility private + def ns_set_state(value) + @state = value + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/observable.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/observable.rb new file mode 100644 index 0000000000000..b5132714bfbbc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concern/observable.rb @@ -0,0 +1,110 @@ +require 'concurrent/collection/copy_on_notify_observer_set' +require 'concurrent/collection/copy_on_write_observer_set' + +module Concurrent + module Concern + + # The [observer pattern](http://en.wikipedia.org/wiki/Observer_pattern) is one + # of the most useful design patterns. + # + # The workflow is very simple: + # - an `observer` can register itself to a `subject` via a callback + # - many `observers` can be registered to the same `subject` + # - the `subject` notifies all registered observers when its status changes + # - an `observer` can deregister itself when is no more interested to receive + # event notifications + # + # In a single threaded environment the whole pattern is very easy: the + # `subject` can use a simple data structure to manage all its subscribed + # `observer`s and every `observer` can react directly to every event without + # caring about synchronization. + # + # In a multi threaded environment things are more complex. The `subject` must + # synchronize the access to its data structure and to do so currently we're + # using two specialized ObserverSet: {Concurrent::Concern::CopyOnWriteObserverSet} + # and {Concurrent::Concern::CopyOnNotifyObserverSet}. + # + # When implementing and `observer` there's a very important rule to remember: + # **there are no guarantees about the thread that will execute the callback** + # + # Let's take this example + # ``` + # class Observer + # def initialize + # @count = 0 + # end + # + # def update + # @count += 1 + # end + # end + # + # obs = Observer.new + # [obj1, obj2, obj3, obj4].each { |o| o.add_observer(obs) } + # # execute [obj1, obj2, obj3, obj4] + # ``` + # + # `obs` is wrong because the variable `@count` can be accessed by different + # threads at the same time, so it should be synchronized (using either a Mutex + # or an AtomicFixum) + module Observable + + # @!macro observable_add_observer + # + # Adds an observer to this set. If a block is passed, the observer will be + # created by this method and no other params should be passed. + # + # @param [Object] observer the observer to add + # @param [Symbol] func the function to call on the observer during notification. + # Default is :update + # @return [Object] the added observer + def add_observer(observer = nil, func = :update, &block) + observers.add_observer(observer, func, &block) + end + + # As `#add_observer` but can be used for chaining. + # + # @param [Object] observer the observer to add + # @param [Symbol] func the function to call on the observer during notification. + # @return [Observable] self + def with_observer(observer = nil, func = :update, &block) + add_observer(observer, func, &block) + self + end + + # @!macro observable_delete_observer + # + # Remove `observer` as an observer on this object so that it will no + # longer receive notifications. + # + # @param [Object] observer the observer to remove + # @return [Object] the deleted observer + def delete_observer(observer) + observers.delete_observer(observer) + end + + # @!macro observable_delete_observers + # + # Remove all observers associated with this object. + # + # @return [Observable] self + def delete_observers + observers.delete_observers + self + end + + # @!macro observable_count_observers + # + # Return the number of observers associated with this object. + # + # @return [Integer] the observers count + def count_observers + observers.count_observers + end + + protected + + attr_accessor :observers + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concurrent_ruby.jar b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/concurrent_ruby.jar new file mode 100644 index 0000000000000000000000000000000000000000..c0d7b155b675c64e40af5d26b72ecbba298f0cce GIT binary patch literal 136759 zcmcG#WmH`4x-E!HQ3Q7j5S-xd?(PnSOK|t#PH=a3cMAk}cXtc!5@^1?_u04ax#N7@ z=l1OyqyDT~tJaVC$b9B}UIl4LD0DD5I5@E5ZvaiO|Jw&13<^wER7LQsq?{Q2+XxsK zB$$FUEZkprK>X`Ah5zzl^p89K{jjW{oTQkjvI?E7*p2MisEqVix@kn|uhbJ`ll4jr zbIe=&4s=qow34#Z&Sg-5lvA7|O-gg9!XiqyFG)v~ZU-Xb*{3>i~W901MU}EE>SomyOx^&?4jKnx85J`IO@oljESlHh)##<0fEov|=h9f+YX*@jc9R)Y z4qI1jrU`njRD@#9Wv4+s}uki1Ge0}ugUx%cx0J|6i z)d=4vdtXKz2Pnu>)~iOoB`&8sZWQs~?MoVXd7lTai~*_{b&a0y@!Li(ZdPzy@t-80 z0urj2bxk19NhGw&9tZykf5~clRuI0&t=uM!n+J|&R<_QjJlmnX5qxpJTz2q zh-8)fH%D{lC3d6-Qmkt~<$I2k`u&OsQ!(n=Dh;v@mpYKddzlw(6IS#_gH}4T;%m5H zEL#N{qPbe|L7&go)D`29y~Mn+4Ix}3R3e1Ze}N*59Vd(UhG&lYEBA0H2BM9z;sI;O z)}$*B*(mIm>C}pmx3}sc9sZwMX?B%dh~YD&D}lJGyT5;ct_G*^bs5k%nS1G0*LJ+fQ)Rd>5cv!MEVXN zQABUz=0q>(WNU32jFO2_;twbeVdPqTZ-u(GWRVi;Yc#=B4 z88X5Mk-$K7$*{io-_eS*-^}8UD~^8dNDA%1J}T~g*l18hr`xt^Q=Qdh)0^x$zZ>9 z-(PvxTxlbvho{_lW7PuQUf`-nIq|PSi&>Rd?vG=MYm?)fSB zSC`VS0_$*0;r9pM9w2}P7&vR}6gw@Tz$&oJBAWDB8p+@xfdLpdS-1u9gc{6O;y6Si zJnil8*wu0UJ*)jwm-tI>X&;;zl_{f`kAH8|z;sj!k`bM^w$W(txy)8n!CsNbNrYWUG$t=c1sbC#ajc-WNCs`lxbH2o z3IOo=PDHkW6CvcB>$f&Iyq%T4*VW1Y6JlwgBZAKu-x%RYJQ~z+y!oPcR37Y#$pYOB zY}G9-ST`C02`;<{Cs$Kz5_zzB0hP4c ze!!~ctjiENSAbeXPGDLRyMT@oVF_EdVF@`aLTk*RCLe!6Ka`FOQcfKos2^A3NBB?b&=*LV--fP>ieomQJ;;Q;hHL?c`%GlEjog^e5V);fWbK z)B^>!5T3@kDx|+q^>G!a{HXe1<$sH+@P9v3rT%IN|IXikLR_h4Esw5_?nC$cyyi5g zL&5~5aRDo7v2kT(#6KJkaBb*bE~K5YPGD!3(vzx*Y?VfC{hTX1Tixi}U66fAmeL@r z-*sPnOT@xxoz2Z%Q&T}zB+KUbu;Dn#Iq5#Z`LMD1{=97lW_I~Gm??neUEtt%|_wHKC-eklDAdExZEUj}&72 zO3#+m8wwHcxm^c+!n|Y#?QqS|I|_HKGccCgGx_{d3afSMtd$pO{et_P98pgFXvuJV z)cZM|>Lw0M{Maa5h_)@9N{?V(YW&;&q#ZN$T=k7+vTo;v6Y3a39=kfOO^zjhCMMc6 z!SJ4G5?V!*i@tM$R>uIAU?+Ud@aV^!SbSGq9Xt8-Vpj(tZiqb)>aU2gctz-02-e5X zrcvSKtvQ)8rrWeRHC`d`qSmpSWu$Ra5%vo;z1J8h>D#Uky-Q8bF#M_Z&yiQpfc;d8 zTdCzuj{gI+CBk)=Cyw_p^Ec@pS<}YP*rR3^%7nd$V?$`SkbcjVgiF}>;Yn=HO$`Di zixW(smtdf@nQ)=Anb3#^@3j*v%WTW!@YYY)B^#RHeiVUBCY^vP58Bat7Wh9bdM~188c+SN(X`ZEjq}6b9#o&-$L0H6r^a=lDEcc*P0YM) z6L+(cTA3@pLbsN#GzAogbrY&t2oit6!dQZ!aM{lqUrl5Tcxm7vMj&OgIn0RMu$2gb zm3~kTsi2mUCjaVtdabi!Z!2|_)X~G9Q4X0@$lc|CPTfL3b!8bPi>9rOC+=R5c*Up~ z9dX^Y^V7rq@P(A#Bw7*fscq{)cp}=~j8nX@u zNi8jThIYauXmZM|QoZ{fe<3^pwkA0walm&*dnI{-1P$9VpZK_ynqlr9l_tN>w{r*} z|GRsHcmitBZj>3Hxk)5+s$k~E?qb}N23_}0Rxakk^uQRJ3Z*TcS z*`hUU_eNobJCAQd35$uBCT$u8q1CZD4qe67fau;Q39|RhZMPI~-w<=2hUhsho>!VQ zF48MF6rCjT?~@u^+4<1=Tj*VV z&|dw3KWU=(Q9u5G3DF}HtJCk{&0f1(J)_z0==@p-dmvEDq>YZ3pL$1^lI>@OFF9D@ z3SMBmM^F5r;C?2)*0Ow!Kl_vC{$b&UlM@4sdkhFk1#xOf@2u<+J9A_HB?GNvgA5tk zgcB|+6Sw$E%_r8&|5vqF!bkG*h6V$} z0RCMM7y18M?K%Eg?hBRvF#&j|C#AI%OfRHfPUe+#BO%4W14XNAzld;%;+SSpSN_Hn?j$rR znuIk069){QkLM2E*!>a3I8?mbf=vX~Pi@oa~1Ve#T{ zmA8Vi>KK=##+p_yjux62d?i9?+1qybPSYZlz{pGNZGqRen&d)HI20%%e=;r5f$Bx+ zl>H9XyP#?Qhjwq9t9RvsoiV71I+2HNZi;%`RR=_xer&qn{1!Xo&@5qO@kxZ|i*XXu z3EcWw0$IoF&9pc;QgkHxx@pl@ULy`ahMri|H*Ug!%?UvKkoEqIX2x2ftU9l7O@1Sb z$*##cC7X#mm;=s6ouxQlPzRta- z=UL-D=i$o_dVO%60cQdf5!OCnB(WU!W?hzckx}c{8$EC7@bAd_b-LUwf}sZp>F{6R zEPn1Ltv1n*;8oeO7JecKVZnw`;usqgj>Z_g_V!=6ooky<3ViZ%cGE&gIBTK~I*||} z^RpLXa-$A;#eqcQ7=h4cYM}};qFUByES&vJ`xc-)T+}N!hO9Sjj~|aKhs_a23%aJ~ z5E@DDsY9N5IBV;jF?tFK8rQo|@Us}Rsw(bbFQ+jXepz9i%tFB%L({cb(V{X zg)WEBzngiBi7^CSdCI4e>>Isux$^Sj_AEsq$ucOWV77;B;aq<1uyXL~HtM!+SS%KL z7z9~M&O=D^v|Cvt-G`BF0|_JbZn&g|RNJv8|7cpZ9%dP=+3S}6T21Z>E)TqZcQ*|W zsIvFt6@3gt(`UxpRZVz!9pJ1RYPZM=JFMNIm+f;;OTW7JFok*R^{^WILi|riGCPZj6Lp6u$t#(IdlDPb-T%(Y*t~dseZ9Mb{T{Luvn7lcqAvzE4or5PM=CQc zIf#xMz5tAa%%e|>&c_&7L}3>L;Fu&NN9RVGzRHOE2TJ4DMXEJ0HfY{Q*I6as5GB$Q z038Isofc^{0ZfD$fTFX`u$+Sn)KavW-ki*<(DG2*fp*ayCmHO~-HEDyHI-ORerDH0pH~is#d6{!CqDo5xYn;aNH*41CK;Ud zQ<0grF=sBgFS`LSH*jVlWmc#&hTy3>-X3-4y5A8vu|RQeYL}VIdRVgZV&Z(Ep;bn# zyW{4r1i7w+$=t{f>}fH@zxYCBmS`AKBr(1Gn~~IsZi^GgUX&lDIn~^YqmRa169>K#N!@NAS)Jx6>psLL?D%zz8|DukRSh3j(!$nwlyCPsB}mH_JbH%u`!wiwd+G=xeh zceGyIu`uwD+jh{!i|iPfc#5#$mkG(}BdA`IKM(QyWOa#Eg=}JkYZoW%ee6FC4u(3% zXTI78ZhMr)QLqWz@~tNwpZ5ZoL_*+-B>^WGTIO73o4*;oWnb~H)WfRsPyf+(II#A3 z%|4Qt8usrP%ipOE{}@DNL3TnQBP$adm!TDuq@p?mEYQ)*3ZNoy5V0wPmui7Gz|GTCEiPx9-RZM%$p^N?(Aj_7Eej zk2*^%z(m{WqUqvgWjB`%cr3h*3~Vh^$s=sk1<|#fqA_)Ie*v8SLr9v8Dj<^DS25HQ z?-(=4J{@w~(HIa4+PqK*=MTi?R?4b|EKOrY**FRg!U>-FP#lQ06{S)NWKk5R2?;S{ z3hfQBbC-|uWl05>DMfGgG$Sj1e&<#0W)NeG|2}GbgMFct93vLq@dxJA(&z>{K%Vzi zl`C7~3pt}GUz9~%eZx(lX2LiqMoV%5>#x#`{%w}Y=KoP~5c`|b{9hpYpDzE0R#>Q_ zE06Y}6$(o)evLpEM7e}?>aX*vzz{@(Q^XC6$rFRCHg@4|P)=Gm-|Kh>qJJYqtBnWH^^>$y^?=ktVCM7jXOziDh+b9>eAWzF8wCY4T6n#@>P>u(XC2@(=txwNB-dVdPmF42A{F z-FNP`eYbnUUb~(fY12Zzi63hU=Ln8udSzzjxE}VIxfByQ>%uFspbpUqwPmc16x%@B zqFBM7{&=`B3_~%cmykAGYhP0@D#B|@#VjS;m~>1fj47IDTY`w8n^}QIfuIt^FTopW z=yLY;)ZbcZtb^}<2Pu$ii)h3;2_2_dF-jteL;%hicupwUWXINK?TCzk>m6FomcR>b zVv9!kLpMT(vF7$WsjWjy%)r$5_WNL1lQvs#RtFqDlj;?E>(w2@U(Gmi?$wmo&wv>W z+k9{7N9{F-p?sT>xY6FB;wO=&sWq&=2~Mou!<&hw!50cfX#$5$&=M0!+SVi1HbNCA z+oplFwVu(-aJSKlTkrGwOfcN2o?;KM_j>+ZG5|g<#HUOtN~o69)wKmffjBrnVsqeq zcKRqt&NEd|+fjG>kbn@1M1f(D!Lv00&07`$fQjvpd=9CEe*zUbjW_YV0T?Djo+SF6 zHcWRt&L_Tr;s~!>IDF26O_oj4Wh#XWoViFo2b-DVh_Ng8g62t**IXtR`V*s|5f;qx z4`cs<7Js=cy1F!bnbyH0&i-+F*;MgV^@OWOTBBE5Vb&ra!&`LM^j;)*C8Kg$^3#QG z^yM!-nWE9Aq)w3*JpIficSXTM1lzkMV3Y(v^yIp?~@o?7YW@Fp92il!PgENr3k4m;FC`0^U=nu-SN>~IDW z;I?>MDrFjmQS7!vu3>T`G||L8tvap!SBhpYcvVs03r?Pre?xmg?6wL)s^<;cqV&^B z>^CTTe1)m9Jj65L74)Cjs?;{sg>y`-7D4P>Vi3G*3UQ3g`i~sQ5OjPsdnj=nF4ym7 zp$VFKXwEC1EW0iFb!*mK*S zME4Rvv*SF!jXQ>KCLuyMV?V#Q8Xjd{TEXbvI`s)6!}aafZG(xFMm;8Qk+P10MX_0? z%C?A<1E)Vv-#blGYjD*A$kyA#&7TRhHc+#-nZ}9px*dU2Yk@A$;?-#5sM|QiQh^({ zfZ?joX;1zw1y&p_!A8|6V-?$TDi@v^MsCnSD8&y^NMCaItzbL4B|G{sv`kQRiq%9q zJ0u0;_$1|Njx>^+-Vb0bb+mkhGY(L2uN3R7?0Tzg>ZG4>r60V6n1qcGyEew@pxHCp z!maqm4MWY57wsWAwFt;!PKS(upiQNx(?JfKkYD`&a6o6E<;WR7Xot^-7yDnE9sdWC zl=)xE`2R@KuLvpv$O<-?*3uwR^eG4k3@BxW+(20UF_-ovKNIcdc1ol-@Hams^5?yB za)o@Pfk(p~Tc({sw1Tyu?HI0((?9Y z#%pQU8;G>!JcOsSS4RS%wZ==IBvrNN$7SM*zs|3~5g3HPV0+y&(Fazcsa-o6*n?I% zaeSb#Ur)+43s5zIJ?#uuGTl)km1)j`B>day7+sn0p9GO93_^T<>m;esB;T87UUVdOdL&;>}-zUU-OM`8xw z8*Sl0Xs+umts9mgh`%vPJjy=PZ`TE~;hY^Alq~<0U6J(3!UM*7*ZpiPB(PapQ!(v7 z){TI#Ls0(`Xza90Ej)_?GAh~FYKxWJcaGxU#_gTGtlg%b4RnyL6v9SsJ^?u#ur8{Q;5i%7+6exu>4@+Q`Y_rP-ID`eXJxIuH*iEI$7()pJ6GKbP2--HFp! zBa=v!wl^C+d`aT9((bs2!O2z|O9o?0lAKFjDeIt|?Yc12)>u-6xbvvYV^!8aitNxw`c zR#NpXQy01BWJetM+p@?^x_zbr#-7h8QX93yf#b~Wed3tPt&4twS*)__QrMQcIapuT zjE=Zd+tC{!@lem1Z?juuj_mCapb2jEpahXGp#t(oKeE%cC1HiwSpq4_<0KxVMY0@Q zk$yVZe3DIrr3sO0r9G|$>9_aMyWb8LPmqFXgBDN}Lsi?n?QO$!+g8pEhX}tIaYb7^9@_WT9Z%TKTUeq| z^7JBi=*TVRg+Av?7yx`0m99<)Sxmj&{$VcLvDzO~e&nX(|KGXE@*lamF88kn`jMNW z$O;OyD?|pODF4h&#@avx+aVY3f8?fi0)l=w`z3s27X2`DAf9y4G{7xp%>kFX(G6hD4l0B|0u*bw(c2Q=1 z#1d&{bnP>6Gqfg${mhJ`15FH$o|)0H2p0m!2M+G*L)|MxF4Xkv`@ma!=ZfhFvdMQC>B zQXcj`BM<`*JP~dcwQR}499JNUBC;xqFp{vVsuHj6%ht_(D0?&$3!=@=zAA zGAk9WGUGdTPT4ZR;H2<}9_#m8k6;y<&&Bvr5LwylR6z=z7I3mxyptPNFIE^0Pt)L% z+ySR-W}u+vQOBNj{LG!#8g(!mRa4qEoUQUy`4bgsCbwtr_TC0J+U8`~Z!<=(($7!X zJ$RfOf$HwxA~WC$97I>QW`$t#I~}r~3$oFds74tap+P1Wj%HNJiUQRmOVdhKhWKd4 z{nX9%UX0ZU>7d=E^Q(6vnq=KZtPsJ>Mp_#RnNEc*XlPgL=eMs6=o`FvfODqXcSpf# z=A9&Tx~WlAD8X(t;D`?tav|NWl4Zu6G%t&svUp_=Sfxj(M;M!^k+#8f)>q2ujjwZ} zoB8$uk3e?wdlYCrqnHC+mT7*E4)Y{9dN@UrTQPP?7c}SEYB(vaU#X}o`aO6w+dDcJ zusR?&_`lj`Cc;PiG=l38gxxR%`6uU14ZlAoc29$%fg=hu->l^(r-o8gfo ziIISfYQV!gd&^5Zju@O^KeFT30q!YAaixDn-qgNMfPl zS}Qk}x+vl$TduS@*_TS|YE?EiWjP))GV~h22(fGqc08PWKky&EK74Z}|MBzBmM|D5 zf*H9|Oj&mk3F0w?6^~z)gM9Y|e0tG2QtP;#wtQUYw z*iTm!Q^oIAs@FDf0j>a})iOdGJrb>i2d#)7`5w0M9@JeAYOd6UT?z~K!q{c>>wCQO zRyy0KEwbs8Qm>ha*Ek%8C>5wkyQFY;T)uN2ZT3gkOHb5(cjv=?iZ7QxP#^RBinn~dcLp>Mry}Q{HWUgihRqz2b z-TZNqK0Iz#4#B4cN=jA5;3tUID@q6)5le~u=HdIEa8*}J)A%lmiWgoKNUSM@fTY3r z-Vu7GT5M^!_=IFyfK0TacefUI5~$T5V{BNej={hs;UX@5q^hIUI{6$P9vx%8Urwcu zSN)~IKtUA=ydZ1OM4eqO)aZXlZK)u=%A8Y)a|Kr< zu-MVSBq9;(-INiOm&Ed;elZ%+j%umI5bXqNpkGcoVd@#CmqG!*zDZw8d+9O==-X=b zeI9U7CfINKEf@I{v~i@aVuFEvWEqBJ-jCoHT9!OX!TRt@bCi_ygfB`Pa8k2WEzM?I zhJFbI+&Gr);RG##Ev$D2uH6@iY_L$|n23nPdiQkU02-$?!bPAq~NCM&;`unAVR03<0U-`;ZzLpY%?H&-?yT`gaQr#5*U3>+Vg$BUPoHegj3R1deo< zMnnL0SE%QZg!09`1>ua5iGv3)YWqybqN`#Dxl72zpITP+^VTfu2}?1i^$&Twg^amv zE9y_Xa6#_A4^5I6VdeIWOy|n>{Dhw~saRRlLA;7`7lVfnKgu`;E*vS;%b)zY5WE%o z?I*&d+P5F#1PEVX;_VSPc`J6HCX3QN)D5b2E@cUyle#Y!ib z%MN!#@v{3%HhpOTk|wS#G82ar;7>VTjdUBfo7@OmD}bUBS?BHX00%LVQ9Ii;$tbB+|l>CI#brv6-Xg+*7%Lu7(P=%wB3zxLo zdhuH}#V^O2TB)4X%2W?-vu{yIt2jkn6yH+Xk|A|8=%HFQeoNmsFdP&VpD(qh%}eGg z6uu2xH?*^s=a1KGmGv00XN=Mk9rwjA^7_X3umAZ|uIplXZZn>9?Y`%$n=sH#J#TqU zi)Mpsw1^!9i)b@n@~9xavr+lba=g|`cdUHQU>Bakw+AFTld%3`^0oEI=A5NDQf$uG zjH^1^;+n|&CkjweZ!GWE`NFGSbL6N~_4%wYdYfh}o|Qb;1gK>ow$ds~PP)uYWr9cP zL7TG1@CEz-#K_0Um?-jQRtx&ZznmB!lLp)Q#;J21^ z#B+G_HL42J%n_07TI$E-v*@o4bhvcF&V{W5Q!T^cn^vOYL=O7d(?5w%_OJO zJ6n_rni4>_cmu&6YjGAduK^t%$V1L>4X z4Nl7pL>3vyFLG_|bSO~y^KXoS+MxgmkR^Z4IX(zcE22OdN96xad?d5ug2qGF;W%MyX8!jt7C}E2w_hz*N;fA%U=ehEy@> zcic~F)R^0ygekkZ`&mir zYev83eYsRKf{Ak!`l$e8sluey%M1=*cu}xm|A0=KUZTF}`jKu(`NgKF^>qznr0;eZ z(2h~du$6l#ZOtW7E_dw<`RTV1v`f6_lR+LrGRfy=f5TmC7V4#(OS63Cjv$C_8TWuS z%AG_U<8P)3RftZF(~VR1{A%%u$%R``xY~Gx!cC&9f=eSXbD?gJdQ?)PBibo)LJQN` zUmQBVFo`a?3P9P{4mrRl2G{j-NN4n3huPCs1@7slhFce2aXaD&>hqy1>@gV7A?}NU zpTbAqWiKPSSySUpDTu+up!phvf}_BzlfbGYVlx`mpg`&+(hq1GV#Z9?rclKd?Y4By zE2=r56aDU$RnqeUw9tLB5JE3ig+btK4|1}CI?nfgOcBvCp{YS6&(5IKd(t+Kx5ZQF z3T<`|y>4;Th=nB~;a?7sC!@LkgzEl~DiR)M7)Ry+>rV3{Q8LzK&|bYfzgtX*e>P-t zrC_STzd<9{;!5bEhXtPy`9y-&sV>D3{wo=cdp!B&fcR@}1(JSEE|z}yW)AF*0-#R? z!K5=Wh=g!Hq}riIyUXc9a3uD+ikr!S2#F7M zo+6;Si)Fx7de_1|rEES71Yy^mquCoWv=|SF6{ixB%VHFnz|$K`lnitC@8fY7V?0C} zT^5$Kzh|*`If={|$8^jqq*M|eKx$DUB9xTflbr19UzaQ;2^h<#@F9%=f4;N^7xyai zjGno^vDX^Iz|sJFkwC~Q4+rBRp9-OX!W}Bl#@tIJbGktjyw5(^>193O^s(G)*B@%v z>!>-~;x5LA^x7Mh_3$gZiO`5jF7fryypHSd*rVjQBggF1ybVt=qf+_SFGd(*EmFD( zAlXN{D(FBpQ&yalJpTpIh=u@!ny_2~YxLn|^_ z8zqLx5b_PQvO(5;65Q>E(v~yU8AFL#}R69;yGQ z;B&~E2#c1Y670fj@MehMXjO5J9$aBh>P{@t1VI|NUu92xSbi{wnbb}M%~SnT`%f6V z-PMUdaaZRUj@aIh;JS{NS(BN^3c}66xcx3drPy>kT1r9bQF+`V4!VZhZbHHkoz%}x zYe^E`m28Z+8H1iQ-_FGuyODhfa8t$IXP?J{zFJT?0}Vro)wX-yHDHyJm(g|VwZ;b+ zKDI`UxXukTh>hGsg6Gje{0#?#e)jN1M+x4u6gVE&t-sRmDwAJY4Qo|~&XSsN$R~)O zSW!4aUR7=~PCb%v+|*z0ch2@v z3wP8tGE4xHCN3qc&G!Y z`Q{L+lK-;#bLIfl{_=6_!D)4}pU1=h(0HSwzk=~gW#~fZiq`mzeKq^H%O3%aMO8px ze2p!Xl)JQpw1&`X>4D`V4V6UPPLbH~0z4i$i3-5)1?8;j<)|X#d>j~Ij@`WL%fFkT zeCj@F0)A@z1g*|`jAzqE;|)uP-@Xnc=A^ z0HSxsRu+wlW_9N<7#36lY4dTg0RK4Hfb!#D!ClE2g5&s~7!uAmM3VZqNgJy_UOr!h zX%by=d%K3qf#-?QGN0v)WmMiyG1IRG6|4rS;he?G4q9s-+O`dnKvq)}prLGPGMSmO zBZkNa;@VK2D41UCamjGDC|GyVx{(4+d`(YqPx63kNz?c(h+$N6pPbR5&$27t0gmlm zSN_|@gkGr=6lmd8GVv1z!F%{;sQviY2aGb6UrrJJ(tyAM7D{bDZ2smCVE=1SCH{9n zmHN+U|Es(u={l~8pa*Y8nUt#~PLe11DCYP{$SK_+P&&`VLCuhJP<jU88dYL~>_JwQ-{|X5? zbTlPn9BYJ)^ebdSZmELTneE8Fxry|I@nik}ZvBxwz$DRwH#}rPn(#+np6;}LWY5NS z`l?BOqMGYz9NllRVbxj{+0O# zhPcc?;Z8x3yMB2BGP!t_keV0RVHhXAwNrkp|3LbQXxBH?sb}Q9# z7u7)upqY|I{ODRlVDu!mm?yzPq1K90jjS0yU2B(yEt@3??M<3Ertm`JDDMN7)@zE| zC*BjRm&#;||)uq6ButXl%6fplrxQN7Pg*z6U3=u3l@f~=eAsB;qZ;^OCz zM&(*IQO7Yhv2w#vVxupx={l`vXY7A~NE)*w#hj&{^F}@)GI%Ie=cWoep3L8N$dw}u zO~Fnf%rbi#_);!TCZ+?^NyH;)*%b;Jfh{sUOa^(EShtlB(EASzuM`7C`dgWsNI{bZ zQ1vPKscW`+ot=K^@Rq>>GgczG_jdPiBN+I_*=c$sU%g@#ip-5!K4EEb=)3vVV$wA* zID-wBE-qpiNPuHw`hZ2i3GrjtBBaTKf1Un4`pKLOJo7gMZ$Q-_n6L3*ux;NX9>cSC zv6rSme`s81_j@dQl$x}Pmd_@v$H*7ishbs(r+F!UP1%`--yN=y-0#I!FvF z!G*?5c{+Pu4WLAG2YV~7O2EycQwl}n?$XK4eY26Cx#{ck3Q-fy4r6#U zlbd=ZhSb{~_Gh`tOIxKH_grD=t|=lMmwTe zE>jtvZsFiEKRgJrZWe=`22GP*uV-2xS zVj@1);23BERho9rKdBQHO2hUhyElC=L~^EOs948YDf4rB%t*#IwJFgv=AFvgJHBvm52NjpH4^4Ox_RmdDyiy=?NFUX(h$ z)@cWGpNI*>T+T9g4E+sIqY^nv3lPKdOYJY%5HWP6TK>7zx5XaG!g!~aJ{4ClJEq$w z5yubrJ({s@H^CCZsv&>+iEGDg8ir9E=hyTL+HpQJt{_5kpm@!BV`Q!gWb%yfJ__UjZ4RT3*{l9eZTWdb)3Qc5}6V>9~_pPkagha)87Qg z&od?sY6y}cG#X-(aa|K%gx6Viq3itgfGB(~ApwfUnb|+nM%V>XbO8wTCHZI4q#dhC zFNU{ycQa-W$`o@it@0@HYlwNyPKqlP*MgzB)iMkylkudQGvyqHFj7Y(d~jRVZOD?c zj5!{wZ~cNGdIuh2x#GkEz1%u2ktsJ>rI?N7R3n(tafPl;(LHoFTl55mTDU(eF1;Gn zMrC{GeSsh?Q2t>7c?AgYt|U3TNec~9^KI?(d8JZWPQ8Vk$Efq}84s}3)G)Mrd-@D~ zYD>_e2)d^G^GJzuI;5=3Afp&kV6J4Oz$QD5>yAmv?OlTfz&0H+MXM2M3SB04M#Cu> zUbU?`cX@ao;{9>CXzooHn=%OT1jHPso25lHRc!LdPmGJC{|i&w>s7?R*iG%LMhgS zr|;on#_6tM0p3tw5MK9WxRqydGOzZ_H(!NMT3zG8i09^xe~*oKdS19sI8L}vY`i`_ zO#XyO@yGE;vIcLUIr^Tx9cO_tuRA(UP-?}(Gjw*{(Yy7t60glMgcx-=gD>`*#$+rc5TlLuY3? z;A6Y>NGo@%^A0@*GyQ_*Q2-b75vNxhP{i0fB|5XTNGr#!30gyuEY8;^Nm&J$3Wg)1 zTyf6Q+K(GxM}A{vsy;`#YnOm#C^jH`z=oM9@~JXDco^!BosfnOwoOkwOdyP_T&V7M z1gFh9R-nHkrZtf4sgp<+V#R=1nUbQr=oh(aOuSL8;LX8AoJ7 zWrCp_yAM6e^fma{GChGMzr>V4x;U6)IDzQksVhG{xU$NkZ5+$;^vk^625ro<2UA;* z`np53_Ni8th^^2Lcb*m5A8xIJckY17qF@ot`PX2Z(>-bv?4o>058#LY#j>I>`^zba zo7>b+hMUTWNgFsVaZ0#~DBGYh=x4TKv8ecZJx_bwR^<+p-9C9)v!7*?Dps>WC{k*` zN1p2YzEbeCvV568P@<+Bzkb zc6mrsd6nlJ$&S*tzUhLo-^~k@2-l$5DU$yG<{l z{rLsM_{BG8VP>J+aR<4^1FPlt&vDOHK{lw7m!6ux`i36T4~1n>?@D1x5WUoba7jOl z{p76$1RG7}sxT<^G#VlQTgf`-0oE%~$@(iBkyTBQnN?2gw1dcmM=SWfa}$hr?s z|3jLBjQW2sWC+F=yk#4< zQkiH|cl5Ft?k`>6hb&dUIzo6PNK80=+1ZW;@TFZvR8DIwU9`GG_%6NQhWNgb&}84T zN^A&hyP~f1k#LLfq3#Jo7sHAyhlDAo-G%Yn&NpeJz84(3Qog}rX64Ylabv2XVywL@ zDjZ9z$2?V@m&p%QqwVXWZV-}H(CR9jd00G(5zuYIWfSNv;8x}+luso)Ey z3V2Xog__!pbn7x1S2Y9prDdh^!uY$1Ogh^4WhIT{-G7f|dQN^ED(Cn0eS@iqWQRdL zn)={&B3QzkxqtdUxZPZZ!(Ge=x3lX12e*qIJ|~McW&kL0fROESf!Ie2ptP0%!eBz2 zxr*M;6+VsBEQ~31??>=mRO?fRK*!V>_wUviZh1+gNp$>{%Lj2sq#St0nd)`toK_pL zaHonL4Pib&h5}2SOn>|d9cSgsGcnTSU&z7EktrW?OThjRSCsNCY%MFl(!x9kSvBqw zI12W1$?vLj^>C|xDf@B-o}px^eIcJ>9Z*UuG9z5j^~tM9L&t^mpc>NO*a&oCyXVSjV)?_?!gTmql&wNxXH8*8SSGhM2HejTu+YzJeyNOHm}oVsv2Dmb zDQczRlbL-*m);{`(hU+r@+*C6*buR_B3|d->|4LU{$}`E$yQcaoSwq@5KHc9fXwBG z{R=J#x1X77`p5@IvV#MXQ5Yq!`UR`*|6=Veqw3t6Enxydg1bv_cXxMpmyJ6?f?JS{ zySuvvhY)PzZb5^)1b6*7Ip^Lxdfa~V^?kd4J!9{mwQALxRW)nY<3Q@`m+lIs{-JI1 zst@fwM++V#=JO%w0?zw*Ik08$}GArZFIVJ;Ag%?@bd!+CuDACg(k*U{?(4X=FeP--6JI zlT*BN!q55U5-hL`s&9iIk3MP&5nTjrG_{}@P`Qlo-Ym0(!ra>xsW*rYY9vn(T%k3A z&zyr71TN^570BW}x@EUVwTrHL)9`LS3~Om?c3|AtAK>lxe95pxK&44)`$}JvWiJR& zeU3W~&R?#g$QSSNRLsXilnDy1xwNe${SlYbyo4Z%7CNXUVn4w~o~Nd%!?797_$%#9 zRN|ozIt-8;bVF=F-cmx*^o36;Y;x3)Q%g}GU}R}t*s@KgIoj04 zEFH1k~q#>8GT?W@zHL7;W`(r z`)0d0T$l4lT&MW|6OsPgasCDB{_{_=-!=OG{P}mRDvFnv1^uO#RMq&Exv9}t!|pjZ zM5hmCRZR>fNCxHWW*(OGW&o|73P;#}jmr6Q;9I03A5YG&a{v1McyxU9a=ez8D97Ox zY>tUY^1TmkKGXw>2^F`&iVNTThoWu!Pc)*BOWT@XS{?LtFbtY;_p-Om0J5?Md%OYn z&!jXj9W1>8&KrB0I2TJ*# z59Gg<_e$dC>7$J+@6CGl!4-jSgRB$oWo^azaRZf|^cmc2l24rtLGU2YTT-jHF{js% zlG_s)Rx%z$GD_Xo%_}q&!N}Ff4&+OjRkC{& zQzmf^`Bk>MRPpwMv3I|DrcNaA(J^nn;P6&}_}3Loq5msi`1|l1weB_X=5fA5ppp*y zgUs=4nH=$TVbB{Lt>5y>fO8cTcn)N}t>P0YPvARd(ijO23cCb0d6}#t*`LMZo5iy6 z#qv5Olo)$#du+dIo(nuZ*DM=8_M#4OXRhC*AUn?AsITQC4!BWkT3X4KVs-+9=+TFPJ#Znr3;L815gS)uR(i zM#mc0Xb0d)(WCvkF9y7>cnH#(oT*QymxyesTAshHdT?B;6{B^9uvA)C)Y6`@@&`&_ z$m2F`_(DRsP2}Y&>*TOtjvb4Pnr2Flfa;~q=|ZLWYzpx~k-aiFVbP-~RPobeX@fx~ zc)M~9oO56p^eiz|u-P!tKffDJX`QO^7ue3%67ZtWTF4Lz-jjc#b;7NZgyvB{p035y zhrOvp@Nt^M^mH0zAz+~@Wsgb>fY2R{qnjl};CC1LQchWIihv_jrxUJuE@q-m7hO`> z>)qfMG5d~BYP_Kq3!akn*T#Hgt3)Z95q4z|y#eiG*HYTX@1w(e-oX)YKR?3o}gE893!&;E*m zM08Lgu!O14`s>*MeFUgDV0_)hZ09?3@!7Ik7=8R=kcn2Y+-3tXLZv5b2bHjKRGGN| zOTBW_3Slitp`p0`JTVSC1vy`ib1i|^sr{WJnHm{8jNWdYR>^i`-(V(1%fX?ijzY!{ zBco`qz0abB@n}|YObmD*AVC>6HWlD1aXQZEJEZnqd~yhw)3Y4&WwVos*~75&od67u zz%ukd2oepU|Pu_2AHxHr)+CF=yaksG^0vfJYz~g{7uGt!TB+C5bp+ zQ<1I8V&zQrI9WDL^AzU|3P&TV5BQ7Cfbxp8kctp@VF4jB66Szh3*cwx1)lmRN9l#+ z@EjUTLwz&{YEB~@MjLm?8m9^qWd*IoY^tQ4AT}n5yVij3W{CO<+HLj8p%vzXGETcq zC?NF0P&hA@lUhCg3rypEYLl=m+KeN+2&d(8x>ilEy`IE4=KZPMw<+Y4V#Dqe7W6C# zl-mY=(oAjIp|Y@VPPY+u?W0P{U^o~KH2Vx?A&-HzzigLKhVtVA@NVfMZo9m4%0^h5 zTir_yWUv%|NZdZrUY~A#bt`i(yW6ga+@ytVnqpW>Z*{tOu8XC_=V$hlQ2chNc}~cA zt-_6y^?6Je6HQ}IAygH3?4tG!T7YhkdO=-1|DKljo`zxIvz30flQ*?DlqK^FdXo)f zX-y~1{wqnda(~MMR5-MI^^Y@Av5f>x{f@@7EJG6Smw@lk$|Hh82-nv&LifGw&*V7> zCk+s6@E0lbjtM^88_L&s zYbW}Q%=%WE!mqSuW&Q+7GY?mszkjm-Xkl0F)KhJ%P-PJatLB?BOa$A^_cdV4Z=eic z0`W)O?3%&+hHhWmiaZEidqPzS>rVeO;flMb>Wy<>deHZDHdz%QCxs2jHDBecRBk)j0T!YNGhgj6qt&2`s!&AJHUT3J)H9Jn?f@X>4OTy^sD zlDny{8k+p-1fL<;d2&sxs}E6ijuk?{!LkzMX3=GMd?&a!%W=Hf6CXjl-^5-`yJG*$ zBBzv$8PTA_Y)f?wT4cOD12b#_0wByo)3 zy@xt51hyA9uCu39V#>hDGhli!%qXQ34qdv)5Z2AEdE1DN6V;5|^Js$Pj|=hJTCLnO zSJ)Oix%Yk{a2x8RT-rHxh>kCBdpBn$-eSdf9{n z!l1~zC5<~%&D_Fml5tq+qMo(w(Bzg11#<<<56sR91ZJN%U=A43kKMTt~9-6|pJh5{l1?irI_ z?N&KiQhnb{KcH=;8ijJYe=7RK;w30K)T~=2f=?}XD3vj26b@L7lOJhK_QlV?_b^%^ zE_45EMjM~KT1{Y!|6@2~N5`XCO@Kjz=7)-7r;bT#r+CQ{$yxf-bann)K8sjLgY6!P zLr_nVy-p1h>m(UE%@)jCh1hWFGrB!5b?|s4&hKR8$!4zP?~Mxfx~=u!<1t8e52FLQ z6CncCYU=WlS!y9pPR`cF+8UT0zjb8i{>+OO2R;RoRpAa259cNo$|^)_gxWQ)R5~|0 z%zs<8?r2zvJ+1EQDfvmv?s)%m!{Q62xa@#UISKlXv`vNQcM!6!+tbJm=Z&c@xA)A^ z?)X(g;%RYi_8MwHMJ>x}4?a5}XcZTv){J0^yRQNr(?Pn}eU+X(h3ZT&y0$HaOeiHn`GLAHj3!XC zA%E(H#`x-~Mr}T+MXS-x3R1WgpeBI6mdH4smmG66MsKg54;6Vh&0Sbio7-GRZaF z@!yJ6r>_RDp?)zN#Frueg(6zs;`qxb2p~9V$2dt78i_Kznm%~yx!LV`T@8B@sc{jf zTc)o50L(b?Jf*-w{E2NInWt50J#(cqG$gCC)6s%@p-_Uq6~%fCAKHBMaiI3Wxgabt z$?kk*+7bKEU)K(M8si^@1)^CZ4cOpJ3)_ehGP;h7Y8kP9yUW;)yvpon|kLBRT5mZe3jR?cP^4d?x-iL55tP zN}AEncOV|mw}T&^%p{{0e+~Ip5Mp5^a{Q}1k@m+d_TMJ zKbBRb|7pnRqS&Ehpajq&>#`L_e%Az!lcKB_{vQx6OiL(6gPWt3cQ8WJ zN4RNAav3j@I}^XO{ndNsY$t>*uOgMJ3(Ht~hC#1^^Ok2$$k}JbYFh5XT-J5B;q(}3 z&6>Hgt}u$)^CQ~=N0{02GV{u!Np|jm>&xG6HB&oN%LTU|i%^YmXl-rW#~&bNBb?t! zGBQu74Lkq7x3IQ$EMMLZx%L0`A^$Uy{HC#M^OtT$vv&O$#}Z>jmH6az$W@?yUQC<_ zJrwCOjKupKQ&*nC1bcHM7F}GwBmqeDr+3fFMQ)ss#5djWqtEFeehc%Hv0pWUV9~WW z0K_C@VS*SXa=Pojq)=9X=lMWGO(CV)nq|Q=bKdmAJ*si`nZ}YZT~%DG^YEPmgQDbH z$;Q#mbUV0S!Vk+pH(`JF1LxAqS=hU6?n2c+XKMfxdk^Vd>*zmT6j2kFF$)!mm~mI*O%I1p%p~M?Dyd(TESB zpm9HI`IjA8=PVDqP1koBv78^2=XVv#lNmxeh&n*R=hSq^S#fCu)-$}SFFn~IT9o*s zH~2xG%h)?IY1UF&KI_hBu%8LxdeE}txL5gbGwB_#;`uR>R+#rGp@Ynte$*|zjd=a= z+Q$S}TafHT@m*OaD!4I$ea)W8Nk+GE?-%HDZo+HVY{7K80cTHEspkFb8i%K=Ir+Yw zaQ*-56aHtg^*>Kox_-#jWJae^NATe~wrQHa!2v}$T*R!(s7Q%O$DC7?1;7eXUvK=R z{_qj<@Ah#*GHex+Il%m6pw)R|v9;6J@AZQbmJNbj9%?Qw0GGW-!5rvl?xLYX+sIpQ z#uL6niA5CUGS@6oG0{U^fR>~KkUa7VNwMYeBkO>hpsG&mUXYB}7FQR2&uY+n!%h>SPzs%n5&XOrg~(rhfsT2KuGROCtyJOB z4sIE>7n~Ndzh;#ToV?=pDA2~WdhESaHt+_54m%EHdTjF>_~=5)8cxO2oeLQls?9IY z1Y0RMwTp{}v!>6#gy<`sAoq}}F3EMMbWBZmF4{d>7`+KDCTEBotl}L!6yvR<0K8c8 zP_m8EigqPjKEQF#dY=iB@J#9~eMQwqE*@Y6nq`mhz+C2Pj7(6(9HH0X(0#f>)U7yv zlxk_cMriPeUZ?d6`qn;w_g=xHGo+8!8v`Te^~>(i+>G<6Zz~Whvs3Wo5=_=x;~Y8W zYtP)18RIKEcUyS>Z#GPk*UDk#n?H#Du^=V;2Wu_Bad~rp0c(VH&EhoZMWx0ROad|}G!dMpk$HQi_0!4l z?>D>ezsH5!|Mg1qmZ^Uf1&vv5(cy;`+O~Ev@-au;`r{rFboWi#@R*iLp zSOGyFmK#Nn;A8Z13v>w)`&xYR3Tobqvd79~QaDnLdf=K<-MSc)IFhMaT%VSYz3beA zr(F@_#);@?h<93+u}YbuGkd`fQ0)@DCk$?*B~-nC@T;L+J$K<@>E}!`DGD082)?cz zoyB zt4|#W=p)e&V3JfJ)z7zQhfV5ut02D3#cmq5NxdB)_a84b-~apoe^-?ML+~g|?dbQs zI%073Us@6;PE#~?!Wxk0J>sO@?*md7p#0KTeihQu)sMMgmBp+tr-D(uoW1j=+Dfx; z2}(p?F?BPa*vW9{;CA+Xy}yU+;#)181O|O^MI(?x#avnMa)LOJkokb)s}ZN#+^cMf zaWuW6{^hD;DGzIqenPpa+=5fkN$BPS@n_3N?E$2pK0Rj|xioVIq?+O^SBOE^8sCzy ztefQuV<}t?;SFd^-Fws$GN-FiT|MX#wPiqJDPQc-_y>_$yl(RB?wcyLh%)&%SR|Yl z6AW5pq_!`3t*-JXggV1`u|L8ah=xs`EOjU@j5eCaI-qWdWfOT$FHMT{ilrVP0}+0= z$pHC~3=x_r09z9H9R|h%WfP==Xp^3%kg(M%sK# zXOq2G7|avXDufBDH04033vYq3R=Rpj0{V;Y2J>M-Xyalc;`r$ocJv_r>9~5=&dTg;_ zj8i@YzNPlcJvLl4?UZVwS$Drv@fN&91U^c-rwIh+bJQA`@9c)5hup#w=SM*fRdA=k z&u&!@ob-ADt;9u2HXZsEA2eKpnQk2($z9l7N0m|{AQHSU<&m8%M@(I6-nnl}blFjL zJ0QX0GlS}_R^l3pn4H0BMzg!9o`m+?I8e;*GqzD?LnQeeM1ilncX*V09;S?KumhQ1 z@LTB3g8GHUiwL;>(t)*iomszP?tPa0r@$Zy*@fIP`P{?5m9+R_0MPZ>`sw!Y&@s;{ zzchwoX>BgTcwv5xRNwc-66EgqUXxJvn*-jycKU_2AM?jJ282Jbg7Hv2 zt7XYS8A0A1Z8HV4<|+J?Ffv=t)W;IjA~aF_QfR>D?=FQRt#rqWko1`ni<)^_JLp3m zC>+f&qW9+<3%k-oBEV0J*C}@Mn)Zc_N*fUiVa&%%=}uS;HQRWUi5=y`ZLU{K3qBA` zt_;BjS9ob&A2@Z)Y*EuMyxq!XH;kZXv~)28F>i{#5<&ZxEf$AXYGK%;hhuA$-)mE9 zk!0F38qN4r{)kZ3;*uJq=c&P8cAjn5-}tE`Ntjw| z5%O0*6F|ovB2tQ7WtGP8>w-p;F*C!0>H3GS7sj*-bKe`$B^*b4&e{4u1;j3fdj zugtPmHP(EXzxZK?(5O`3rE>HmT%P_5|JI<8trabfW6AWONoK6lG->AHC)R5z&pb6( zvv1n1k_u=HFN!h9Z6m&cHVc|bGJKKAM^P%e z$-(lP-?}=}5Ef>E=iO<=kD2hPRV@XHME&s)J#m<7AxOtsFAyjUcL=~kjp&0y+YrQ$ zg$6i62Sc$@deENEx_j_HF7Jla8dY{<%sNp#NV-)+unTu3moRP%0iG?FS#s&)8#B>* z879D5o2|`hjG~}uH*up44#344Pgf5*;3}q*!or&U-jC`Gj9n3HFjC2Ya)BrMeWXUk zC(li^{lK^=*7kG{xWgUo3}MuS+C`3cjNC2D?=j~9KEkInVLg;rRVM2MEJ$!fj+P&r zqvIT&K40*QzI)~i0&*?*pX?baVLr13(Csiufd;3j#&Mzc%eAp(Ht_L6xUTrnzMbKt zuahu*(Cf$0^8wnl>qeR-8c)D`8SFJ5ctCJ&?Y|%S-lq|7VRhLGVjJck%K7WL$-g|f zg@3~e%20o*Mg57S_Al_l@8?F?#l=a(!S*fXxBX}1%UIHcD!w@SKqtbtN?t@{kx=`O zMv3ni-UG3taO1HTr1Y$nX@lr#37b4Ecqh4*3;0$iiFW!Tip+*-nNd`^OD$fJ zU*SjQ$9kYxLbQ@p7+3gL99AE%nhiT&wrZd|!MQ@nq4oF2iML212!Wz_?S0?X1F)?3_h89$5#VaUTLW?ej%}aPKSW-amMe|H-k}=)Mp0hqfmoV+*ht9x@s)#d} zSTc|AG5R??NP%%7$XxX99C0b)?Sve1dVLw&fJw13cDqy^AI|6*7DTg;CT&Uu)LvyL zRS6Z@ZW>rLJE#ch0MZX)oGV`aOzjn)8|kmvQQS@@9Te$!Un&yt#(QhrIpfijC(i-=DDm9IcX$}0mJ zdy_K;Pd~920oY|OgZ7ZU=E1@d9&QPH|B2FPe8i62J42OsFX6kL{T{N@pUEOLE6G6> z+fR+RT_k#4nO)*~Jv$lhS;*B!9Z^c;8Fbf_^gRF(t{m=5UImPjX69BioNh4f=4;p;TD_lgO4>V zZa(%AJlr!7^zx&hu}Yj7r5KY1Z$|l`>uWWPS8vE464V_Rgw#bot^IZ139%;m|Jt~t z|3|j`pGI!}bl?AX$w8Hdtiu~E^~L_V<=iwrnQy6hViKzb{;PTvw)6)G2FUE=BiRq z48yql@Y8vhch7t8r}JJyr(heDkst%DRv?(9k~j4^ut-9&H?!-E=~9 zo|%{3NI`CbIy{R9z_UlDu<%r+VQ7Ko7fI=WPV{G*6Hy4z&9@edb+||PBaOP;+z(^; zN9wj+62ONYYtL?$-L@<}-}LgyQ?4cuazwF8QXVdri-`m#NIufChy4L-$CRD}z&e15 zq5Cxoa9ci2Y97o>CI=K^<6t1xQU4i3fR4}JTe;zG^%!bpW7t zK>9d5snrLZbOO#>?3HQvv#~ndojjoTPW4Y!=Rt05as-)RnaH1FW*fzZux{TV{RL-w4wd#oR*C4pRUI zPQe~4PoQWpwDQbh@P!BB>(j)?Ux(w%*adk8VU@0)}oCq*paot8>VivkF`m7^)u3qM8Xm8GKu@|1jV5ScdJ zE0YQ-C#bfz*c=z>?Z<#OiZzkyV^W|aHMZi@YN8y+d|HZej8qC9mMCMvk=>@@3Tp^2 zVUnm+nqzZdQ`KXu3j`inb05YOTON=13`u2cIO+gVsPB(CP`ER)nqK67Kqg#z? zvdGtL-byv_J0+~Zgt;esecFv-sfL2r633m1c6B5wV4Jey%mjipt1mu2PQHyc(UNl! zn688jmq`ys!;~EguWttfC>hobmm1agBoN4HWicc=Wgm_j6c$)nfIvriq?Pt{p3`0*7So=ZVRmuRcDe2oYh(LpE5-6ta(+fGJyR-s!e z(nTjp@n}<^iQ9z9HDpw*q}#ieIVUfC-I2p|S(MVkp+s@B*>T=BN3p>}`|8zRFEiTM zCTkyAEaq$39|}klmKUi^m9NdThVt6U8+TN|k#khgsu!=Z%VOlreCShf*Y+(8e-5z~ zC3q~`rMvDUw9%<_|2Z8$#@drA%TuIlHt79ZG7O&Y5p z!+3%`GR>isp(IwT-u#{Abw|R4^c#}&4cn7mf^p3V`Z&NP$uEge64t}TwqIyRQKRj- z%muN#N#_JbL2T&^yC;)ZD-cjYJTt$vD!HQc*tpJH`YX36wBKV6!?yE=1NGMzAENx= z4f*4XS9=R8<307>wg7t5)Kb4^dMW~h$8dM|7aGKN;$Ts6{A?r_;8OU0v~0!8xRP@y z@}@YxAC~U79s>Fe5{V*htQ1@Zc6x6C-{1>A@$=<3CC>-&V2iEz&g4|=JYJZ)aIUBH zj{Xi|(vCh)?-2ew!mPV53?)R4=z;)bLDDEgm>tcYR^g#nVX4jyK3~cPJomJ1%};1G zn~FJO5bMp8gHtYWkKCJwb`OIvj4HAwtzjH#g}2*|`FD)vjP#t;RMIyTImcb#i+B~h$+#dDZiwLDR5y!;wdx?-$24<`kgX~ zOL|i&m6b4>dK2ld3J?`*?Sos=TIrBxNSCeFP@|!=6`GEnMM3mAq{-`nHB_PtS{wD#}_=`t|@sf=)nhXDxb(Q4U=y)AHR@hy7=_6-j*PCD= z>id>{>9dbfwYF9gX*k?(JhG;P_!FD9ZwJ|JMU4z2+!p1$X1#bUcG@Z5A1?70tM7yJ zmUZeLo+4g_e1-PHIG(8`Lb_-vFA#KSsrHX=%wjGug2lH})KFB-PN?7AA{defcf=S2 zk6IIYhLM9dX_QShKkE)x{98^1j^ zkC#=)Qe0phx(te^-tZW2$SP^$D_|3mYr4gMo5+Y$h_c28wRClKx%AZ8PMm3cu{gVF za0pIwIH5L9PIcxVkn$21D3dxjgIa?veowek?DwUV4t|f#8+Gr#uKy7T{Xl7fHni>T zXYAxHvcB;-mzR8G1Y=Z2fbznF*Ur5OblU)d#l{z9@%{wvM181NbD6V`&VU!F8~EJ8 z`;N|SV{tc8+Xt>5zKbSZn%Adq{n9{u8X0?mBEC^w+H?k&1$B`$tYdatEMNh3F;2|T z$;g#;j;7AL&3D??^&nno?K|0;h984X3&}G#8z1uzx0mNkYM9wa8T1A4l9RsnfW7yg zP1GJVktBMH5n9@cO_a@)gelkebk)Q8ckMz0`iXHLDRIC0W1)M?fJ)BO5agK}*F7nw zO6z5>EFE&0EC#X*IbwL^3%aIXrhx*esfV;X7nRh2_D~9p91H$!6Nj>-`VC(ZthZG9XmL9NYU&=mTt8944QilV_!6usoyjAt^)zeZjrYseN@DHM zIGiUp;-AO)i1*#TcfGnPcTcMM&c4@Fm(gk(i}4bI>l;K=kFUFXiPoKQg_qQ|MTGpp zx$(61>j%=kbQ>QghN>4e(8Q-KfVQUolPA5=tdbsU&#fLqk2^vEtgrBbHU7xvEiFQ4 zzXSGKyPau32cgTxm};u&OBQhc+$-6+S&eQfdhY>Y@j9de2hwlhC4rl;AA!63+3GQ$ zvPUa1zqyIglO-}k#U;&TSi_PW^=o4{+pL2H%+NSlAg2b+Xxez;hN7B0^@Nlm4tsdg zXQ|+9m)^L0JywRH?pA^r0TgJyT6y1I&rik}_z7-nY(wi-O}4a!J^(y_;a%XLE|VPQij4#gbD?9H;rn0_ zG)n|M-7cm(f+^=TSaKHWsbt$j^ogKU@7_Is;JKji4_j>v+0WNf@*&OY1XTVkLCI2Ac;fFp|T6#kb^$YqpSwP z9ZgO`vB+dE%X{=zg|jE-HBVBJLxZJg88-VZ#J-~QBfe5f_WXw}v)*eloM#jL2TCbV z(YROvJ&8Kjr6R#H#r*`?)Q+e$XD9wV!3smYo}Y&g+AFhrDX|sVd!KC}`!3@@=YuGE#?<%Zfvf4`pBC`i9UCz3T6XuS z^9ku8Z-+cNm(G4%%&DU>IqZn5uZo_#V)IwymBM`)jM(XV$_TRC*|HfGZA-W8izChq zt=9H@P6~5#K*p1&2~I1`!{gH@$cxTsGnzi$qM}`++9y#xjR$P)SGWj?I zvMll}%CUHzLda>7fKEJ&Hmy8Phzr5LGUPGmdL@E4c9sv)pPt{p)*k<>y|mWOPRtw} zW{m%}_*e?yZ27icgiORr;^q+?7pu0`o3%F?UD@nL>}%&0ZU#vr=ni7 z#K0+6O`D9vpDjn0@oatjvz`C^f=^*j)md;CW@KO-wOjYvw0SqHHm647h8 zazbQ!C^Fr2(q__+_(?p98LF@X<#?{09aqm8mtJ~0D}bBbK#w?}G4_(pZGIeg!eACt zm5+(>@R-6IEz}Ng}f3!Y$o{?DkEHAs?RW_J zyIGwjVPARnX1LBjBAY+K&wp*&|1zx7Z^Qb`EER^SdtJbVH(;fZ+!#eD!S)3dh3qmc zo0TCrqPf-^`&B{zH4H-uODM-UZf3rkaci_Xu(v_bh0sQf8>E}m36q4kQ}v_RyUw>B z>!Aw0tR6Ha6|u;8`*Gz`1@n6=C$R#|idu(EoOC@#g?zcXwB=C#;7w4)%a)-NU#V!2 z<@aS=ZO@7izkFE;km7?jhD<#*1r?)>ZU^+XKA%)gU+VWar8FW{(|*XSXOdXfrpTIM z=;a37oif45N0WX$^Dhq#v?5;T->&+?u_dS)boVVMAH*+F#0?Th_W3Eh@4wpitT>zRjqQqlG&3J*!TD zHu5IYC9!3mAHz`pR~u*x)w8-Z1*VjqS-Y0O+wXLbi=9dNDK7{2g|9!KD!xo7LM0Z~ z#fn@6ax`=xNaPjAe(s$>`*m~w;5jcy@d~J7v6l~T>O;`tNgbWOi}RhZ%*#o43w>uY zSPhb2rVeK)Xv}@-Q3d=ES&c#;o5N9ANUscGA~)3vki9Y>(H3UyDL+pBZf+obWwYlh zCkqW3^Q}P79?Wyc<3N7mnr_>XIo)}*Mq~&pH*8)kSht#L2rIu|AMU6ZLgiZ5{k++a zU6%V7hD1f$jih>FXnrkOfnK#c7lX!!^$XzvSW^@U(Gy#wu0 z%eXT4=-aC9cwOfAPTx69`t&&KWuCbEJpnFP!SVHgTX`EsALKD`>*Z)0C2T~A@2H1AZ1u)8!VZb4V+l( zc?CP}U0wa2o*oc{ATi*$x8<=p?2SSJ4O=;P2Kyt)w@p(U!lO(L#D$@pI2ZP<_W51w z`(mDwBG9YQWzV7p{(VgN&G&uN0a5v3D0qkx)NO`NyjP7Bv6wN2mmjY%98O>fIdGC! ztOYAEX^C}@c4&3OiGZ_FDZw?mRDjXmmZ;@aqtqu^d{N~~cUqX1xqK8SDA2Q3b;+VC z$H_W_W4;FVZcV=7*$cw6(?}1Sx!lj@bFg}N#(@1nI1(H(8AlvH73rZHn`gf4Qn|BJE z{6&oYCrMZAw(fb;oH4PPE^P8dd3Z;-`34SDY^mQ1qoX5X)|lyIX2ja}oD|O*UQQzI zONQYE6Iv@~jf{FZtTLT?bv}YmN{&cIF`?h{qP3zH&8aME>Q^_*`RXL&`Uql6aXd^> z{A?fd`0Bae+e6WM;V5lc^b}YhS%IKisY*?kHy%NdlX8r&@p)c?U;_PrhH&~KX^LDMJk}7Xn=!tik}1@D2z~g%%%vS;Ns0KE4ip(3v&j*5Uke zDeKVjdW{Em0>Uzz{m{Z_GhSF%97nH{Y`+kr-FM!a=sTw%k5%b4W5xf2)z4LmR_@xS zp7h%@GV#zEP3#8RBv)0|oQlU-svJVJ;*qwlKW74~lWQ}WBAtK=k{~z>IwX9#|G2vQ z&n4$lKeCb>;y~7=N`HNy3a04;=r8J%LAhXGV|hz>?>z5sbRda;k_wGuAdZeMIgbxH z`qmi;r%F5B){9K5v zM3}%QW$=>#1G)jYDp_I98zujQwv~i=*lou#RBej{v0FfABq1cx&NRZv_y_KJP78DS zKx<=n`{X(NJwy&;ft!RA`Jthm!VF@D0{$YXHm-c4FejRk84n^yQHv$eI`LaIVwU%Sobh3 zz;KOO`VZXmj4_qYhO?A%1Bd%1=NIOjBmmlJYkkg{%jxUn393wEHTm=T5iaRY%7Td* zY;4~wr`m1U>4{mrTb$hs>oX3OIL2_kcM83O)C7|H$8j*e^Aa1u8d^D7DA!TSoTj{p zR1Le?f%nPfVy)H%ExBjA-c%3odc*&0N-1y8aT|oDqOEvGWi)ZfhNX;Cz39*KA;f&y zrAD1fqkx3oIn$k^Pa_NgE88ANmIsA%3luO;r^PyWoronuLqjliE3c-e`x3EQEJm>gu%A5R z=hDVq_b3#udKQh8z74-c=CG49EVYnjL_d#TE{EN4Ox_0r4kjyhCP z>X)VgPWNy#4RaH3Qzk@de3id)p?Py{S$#+%H>f?2bXqExI%&TB%W ziv841KO)M|lkiwwOfoQ|25`iwn{yKF4PhLzFD)C!A~3sw;8jCPz0S>t9Z$me5#z&2 zdy5t+YWpq8VIc1}Sr{>rO|;DgEjO*m_5dWePyjPoR?2&O<7WRnm7Q`E5EiEF*`;WF z+cDT4F#%bvQBC(iN3g_=9b5hB$DWP|`eUz!aRW)bM}g^M1k(ki+MMrU0ym=gW`aGS z;{j|F!ESUfxV;5M$7owS;b%Lx2n?2kqzx=coREVVs0Jw0)*-*xIYiE!N(uv}&0tY2C396Zv&cDVIJ7WAA_YCWJV?(yEyl>RmO?ac5e?@?A z+(|04)<^ZoulxWlS1-7U{)jeSC%8p@gT)83-}JcAZ0~&mrYx>G20w%HyeQEXZtWg~ z`GiI__BkFxUDGwvYE(MI?tSF*{6RjA206L-@Z)QRCJkG8jtP_??qdgM9QdXN?)QmP zg2~kC_Dy=}NDPDDARZ|X7dok0ZYPIdeu1edxk0nIc}4U%Y}T|NZQD6@^A7Jp}*K#|rI6kcAV_JJO^SevpwoJr^&S;^4 zfDr@#?N+t&c3OtoZ*k3V>R$?3g48hZW}$j#CCFwe8Y*n?yKIE5G-2Lk`;kL+k?rGL z*}p5IW=@QP(p)zhJlePxA$~E$OVzD>aUw|g>|X7ZprLwIpI@QoVF3b9Hn;Xrn$J_v zkC9-H)M&(6p2h5`a}@9AWW0D?e4Tg=M!Hcv4Q~s6av*Y`wap%#KRDh-!iH$#6M+KO8+JZ5OetaMh6%1`1`Bo@b~v`Ou&2X zFfRZF1!V$d;0i?{0adg8r1!l2)V@8PpFi6kf0sX9DDylUj{01=Ng~QxujXUXk|}BI z2y`$OP7My1^|ew_C|4y9LL3U2Jcg%>ga_9SGYfm*4)Zv8c#+mF8zPT{uMC5PYH$DQx;LM0;888sq8HDVE`1qUZ`=o1}j zAhzpX9Wx6P3lpn980q9jCA_T=CK?29>bBAP`)NJ+kL-Hze72dtaVj3PVqgE8g*g8R zr2fR4`In`ZH|+m^V!M+6x$Uf_1cJ;hi~y#{gEDlovlG&zvh%l!!!q&=08=A*I;z1k zQ&XdAjCjwxJI|_olKE zF*Z&%1Mf4FZPEpQg+)seL-k;G_dCCVe!}Z_H>ZA+AO%c?xSCIl-e#RX_RZEXyIf z(djHD*Ru2&pGl~g4-=YTBlhbn1@k7TD3z&gnWQ?2JC%p*d&BtCQf*O5LV^nMI#R84 zdFz{M*?8rdX(-<9_9BXY_SRpXRug5_{1Gy8B+?9mEyvbT9IFQsYp|07Y??ytj*Mp% zisS`plu1o0&8T39Qz595WRAFT3*`pHRam!0NCz<3;^cJ~r{(mSW}$fDxa|R!&ZFAA zW~FckVj6}KIL3i*%Qk*S;zDZTkl3>bzbdd4&e`A-v?#o@wakDItRDU)iDy47_8x~2 zaspbtYx7185_xl9gi}=7d`4;!o>^uqI7U>9<@QtQz8O`rnMtW&b&M(uIDv4f*fac= zy&gs3=GLVqzI@Fjb!ljc+}GF@EzG(6CfnG)6sfB8^sGipfsMmMG0eT5h@mrVvr+27 zV0**pV{e3*{gHizeMOiARl!%rVMkQ|04C8L?Rgh=xcS}p1IVAtNNXf|FGyK9odhmS z-z_irja-O>LZ8@GSu|h7cx(=gdC1`wl>DnDS(whWXV5ifCs}afl#$J_KjlR!xEoYZ z^Ip=W5DF^5nqynTN@q+N{$tzrO&NWYo7t!hR@~_B@dM9@hbFIVVyesUxcI zWu$1;|7m%#56m}IINghB+sK<+&PzaoyKhhf`UR8xNgvTIL}Nc{c!NTjOnVC16Y7;1 z{PF*z?VZ9a;nu9tiftzq+qNpUZ5tI=RIzQ_wr$%sE4Gu9s=fQ{-u-uf|I^=d&dppm z>t>BL=R3!XF=mnGiojhr51>Rgx8{l?T}*MBlaHrY4{wf-XAj*nxJGntdnm=zw|&z^ zQA{fl-suJE{>?0wTfoG9KQ5-&zy+XV8=k(5Tx(n_iFK{p^^QQSLfDfapjXC{Cp2?e zo#~OzY+uhGUlV=a1ap0&(;h_ki9ndevqdk)nMSh2hs+MolV95l$|+JHE!!QfDf?~u zcmr%r(z5&j@Z}G>kDT1tW+5ltn6Q$Y6;ezYl1)=_dFC+js+R?;slNqKo4Ja3U}If9oQm z?khK2aiFKvZz(%=O%KT23FJ|dQ)D)eE%BKWZEy3ME1f$Lm#>slQ;i>p&4D5!7_+G@nSr>M7EX+FE=dPS+b_c&(2ux zZ@R&mojM@QEZ9V>D3HTMS;C%cO~>@;YC^3eHLdd5cTt{?!>I5HQ%7(_l-?rhb!JCV zBR^ECl})ghQZqrPC?#UWoFeNX+-7H@hfb&l1IY5haCILHtuM}GoG19~!YdMkkRVeR zwoC^&ArulhWW{Emn<7V-bR;U&Q3>Q~r3h(@Gy>CV> zx+1|ahg~>Qy*wg^m~HBlmD)=dSDzGS4$po%)`Bg8vFI z&UCiToNXcYQdV+Uy4c5?gJ{z>H^e%~dJ?I=h06RAO zVg!)RG-$w+hk>>n>ir$>00G7whMrx$I-DZF&>igUeNt|=G5C3}sLHp(Slz53z8Txu zXS~Ns^wtxp+$E?78+@Ww88V~J|2w58pxQgK)iw9y-V69>re4fJ#Y_wC1h?QeB7Uf; z+b|(zEIy%iDlk?|{15z>kWxvOcQcz2U5LPS|+hHib5b+%-(2 zal2^08w6!ks>g9msGA*kP}-g3*Yy$PeWqjAR*hS&Km4}W33?$y@~}$Kn}wqRm*2ho z>2a#I#_!I)L7(S5Q$d|<9mCMCvrE`O7a$wlQtuKYW6 z;475a6Q%3krs%{bLexhU-CWm`pEwfz%zF|)BzTOVn21=t#jAa|C2cWFvv zcUorLkv({HsVR@HdH&h>`VwCPDuq-T;4y_v-(OJi3`{o6G5o zc_45CK@s|XQ`T3@@sQTnZt3upS2nkUAOy0|=i`$mCiD#oD1d7zVg3U;jzW+k(xV ze;1J5{(s?@V%DDzqQYO1Z(@L!pvVb z++3|67GZcOs@^LYcJ|e_J-8o*xE!B)ph6wwS|jTe)r`Q?ZugIrKTh6zH`7PMuJ35W$puKPaJDe;|vLsN|Saa@UU2 z?;NJH4?R4^S;DottrUe~jJDVn{8@O zm@yEECcvdWDzXSffI7K=u8h=}yb%duRoO7tR9adlRCLGr!dqU`v&hoeM3}LlhIlN8 z4nvcEe5#DCSCVf2ixN{@e1Li$7F=(8fM|(F&;$@}6IS_Gt4qc;Ge25#rvxfJ3T1Bw z2P}s)0_gN&7$b?`qmXJ;m$+5<5){W=U%ets?HR}Ff+I7D>b{)@3Kr^eUFYctnq)mz z0R>s(Q-RQ1mxx@I6eC zT6^TNnEL<@Vhf>P31jNjD2BVp28}fJY*1Mp$Mr>{hA=8axInPlF6)@&^lS;orWB+s zr^)vBVT}atk^Gff5In^h`|QXwk&K0hkCCtP>X`+q#YxI9Smp$)B^gqNg?H!pp(7`k z0$G-aYm|;Oih1V>{i@eVCq149?~C)g;oIpR4a?6WOxwDc^YJG(tM}H1%W4Yyc0SHP zCsP9QB38%lsFjxuE(@TD6;K|S)iO2|z)6YHylF84=#X0EsX}tF?4cE4nsVREF^W4p z2O=v6*ehlePqH@A`I*MGZVU0HFLvuNsV-!hxH`b@la--WMhnrqGIue{v6ILQxLAzy zPCNty!xK4R>T~Jx(#OwtT+h;vDgGn95i`c7&B&8Ln9o&P7-r zWr|udF|(0gV3H?P<3 zQLdz+@>`E2O#@BTYa{acMu~1J6mdQ>B!tSWG7W^Hw<=jktf61G9wI4{I=PfS< zF9|;^N9bt91G>18qvAF_vX*9xz1T_q5d}tvC`MsYk~rDA$M13zXM_8e`gUY3=rTnk zhtQ6*B^4>P(6Jq=Fy9b7a{%s4;kOXB{fFo@pwdzHms|8v(VHU;sVnK~24MFH+4F{< zwN0sAvhv2j;fRAx`5Aq0WG5KH76n&)mFpl((Wbqn1FA9U(A)O(MoKaWuc5I!#9Q92 zaEc@ZSzSfV1lY&E%IUL~B!B+!&o|Rma#JJ<^oNWGF0&FB#d&+j<-Mf16DN%s1B&w& zYu2R4kKi&2;;3+)ZLopb>NW_%f4=*9;Rl=$AI`TGaE}ymfHdte1_5N8NFne%VsP0} zq<46>L>@ho zXY0Y}#|AJU_iYvU3IRGjiiJ+z>b9denXpt~O-J&s0btp7{=n zy;yFV<*>|*pWY7H!#;SY+DP2j#;%|&6~e=G{dkvGz4Lj7w|AHL+9sWp)YERQHgs( zB6E%{S36?G9GRSvRRgLKjZR1of3+uyHGaEleM)v7_epYFv^-9UW@ZJ&5#d@ipXQ8X ze~`HyO`)tf|CQsl=1=rCm2+n3sbJeFv;iP;;)HJAdScYA|Xrg7t@;$^hQ9p(_ywlT|eME z$Xgb!gpNDTYNTsn9OOr}K&cwO0W~v$>SXQbjfKx%(4=hEk84=ouzL7!xxyyi^!3m* zQ|rx+j88L7vQMX**niF8ViUO{c5P%EA%7kzwq8+0VtVn?N8?hu-n;g5cG9?7yzJ<^ zD_3ZHqA(2yGkd+K3|+c}Yr1OjQ6s(bzD0+bK~>MQauAi7B0W=;6l$WGBG{@!|#H3a%`RWMmtLHT0yOzjKKH^*T0b8DM*4mBk&dKtV^~0=9!-Ooc0l zV7ch@)loiAc!lR5%BEn>?b`5}K^XmI1|j}8c&H-|K(Rb`$?sY*)rZ zyG4OG2znSS`u|FIMv1%AgUQ{HYPISZF zT@ZQA=-n+A*I@Xq64|lRdEg zss)ihQN~H=Oqq^}KR76gsLo5^<^r6}qa>ap*H<3DAQZm!(Vckr69OABJII~PfVy|M z0&uNSS$4c3aBVmHTv6xul}r}1_T2G_7tUYe^>?#_&r#?q(&nSPU-3RHYbsE+hFM5o4WcE z$bv^;NZz4PglJz|ZU%n284vhdqcJfrr$zplxZ%2Z$#`gcxw|*X1Y!%#M_eU{lE-MQS8J&`&vzkrUmAy4&hlG(sp^uQZ3E|VkfLVe`3ODLgL|$4#XWXN zbQ8ALz|nk*G8e_lTxu?tcWi%>0MlX3T9`$9Ln*59gMHNkTX))iWjsKB8Tj|~kG+`; z3Jx{nAYi36B_=ES3#&44lVR2BA%=1=o>$t3eE!yq+gW^*9Zp=APai3J>O|wEX$a z*omgxVx@rN2q|!R=id1>mQhf@`QVyPyP64A#_lSV6SicrF2}U||QJ=uMUtgl^ zAz$`WVKE{R1H{7TNM$cr$T;$%Kj8TbAnXc=i8i2JzVd66g5Sy1hy|Sw!Z}F9Q`==m zF|~UZLc9@X7n%7NMZ+`O;Qkzan8NjnB+_2%srK3)LIq9behg+SI`;dD3lC-l6nYFc z^?ld;S>kBaAX+9m$2G+*=qAwYXUf72T=cl8KU_5}5*f_8u%|L)G&vS{j99q4Uy$8k zqCg z!y5|6g+Y=&_k;gjYOKoF!uZU_TU6oAku@uDu*FwWw#@?1_Rc9RFzLQz+7hp;OA=!< zq_U8tn?o0>skE$k;WvlqcS?sgZ+Vg1@4q7lGPefn$Y;ag@-N9e&)>YHq`w>f(?}#= z=}bXU3H>9z*T2=R9h}A*z$d?$I<%%pYzUJUe~2KbTGS_5%ZawC$}RDHV_!%r+%`?` zc}@~nF+?0&1EPPsiG}-u<#)s6b;%(Y!YR)nA`Plm5hJD82!)r$4r?b_=1os!t zt7_wArSz4jJ@dW5~F-W%Uef^5LwA> z9BY^bW)`|KGch6<9jX}cCs-_qauew@6qHJRAYXzb+|y&RqrDVnN@ti(HFOphNjeP>@ zbyAEySLnW6m19+-3fF04Tp(SvWRHq*2Aq1qz^h@!Ag8WpidO+eoj2dsqj$Rnyce@!1fMcy%5GMbxFAU{@%3}{f4Bs$(}*7eyl<%slRz*!oB zI8tl~w~MAHnAW5+&N8aNK)_I7f`l-Y2~lB4L7yaEk}j4nU=^Oc79_JlIlc#*kx=H`rRGw&$pnbgr>DosW7GH@uig%Zwb zNa$LL^@j8nZN_P@tH0Xt9@uy+)5^9eenlak$XypzJc;-fIOZ%WL$qVeA9tG+@?e{` zRTrhYuBfdoJp$b5&hm9gc`7_AtO^pFn+Zq)=OkC1fR7kY+U-s@ZUAqMOn$QJY#ISv z-MH`Qj(22!&Mk)tl}BTpwxCQ#2>1=zVGRe}%|H(}lr@R7IP% zo7rH^@7!^n2ChJj-)IdR#&Dh?E6wPMfGn;v1^skJq&t7ZnV1NXTs)sevmK$9>Qd08 z3J+64Lo-Q7{Adn&OiFs&O=CJqpc#K>@hzD<6{zH#O+PMSPZd7vUpD)0qO?E@6@>+y zS9(xadO+FKZgwiwtwcPD7d7CGY^ctz7CWW?rkSIGuDm%eDNb?So@<_Dulz6nGlN+fc9H!Ha-WhQ73Oe8d znR$8g7`MT@%WCWG8EWy$xwfT%PO`?p_RfcI;F%jRK9fi#5KZ56M5=&!{5>;f8gI8x zC+dTU1~x6nq=IR;FQq1Ooe{iXnq14Du#p8stR)ZfB(Ud#zNu zD{El_b}aoC(MjZ~V)_7vTj27f8rwV2?@(@0Gz6gY=@xMCm%ZP=J2&(X%K(0te|-M? z+)(L&05&9JMEcHy9Nei-5f@Ao zof>=U%SQ7Wm_6&Jj>Q*&TP+80xN29E>KNPX`lzQ;nw*&6$uweNod{u{agTOR>x~TO zdppPHufzlszBLQ7<4OqmJ^eJ#+%uT8jAm7uw?4CgiNb=xBj{+q~)o zUmG9x;K4bIaFz#JY);Qt%6+*V?gU?9g8PJjNE&h&8FztPonbMq^@Z=$)S}B2xDlh@5Zc<*(YNW+r@1 zIU;4fproa9{iue?okU zKhXw1_cjMXT0{Nk-gf)k+a3Sh+dzNz_N>64y)D9K`;WbC))a(%^9g3#U&8%&C+Pm$ zDDtTU{cTG-yQ1}@ydJF^?ntj4Jx^9psE9geYA3tD)KH*EOTUH)tGe@``!~*(P(BN> z_AZPU*_J{7$<0n(2rKoI(^T&+`S}?SJ z&G_D^W2NBdVBCgsZCu>rlgoR~RU8O@##x?^O@5x{K+oa#&MS$;!D}S~%#Y+K>--H$ zu4q@5xeDu1DgjSx7iR@PVUF>IEhy$slS)o_ujSV#zJY&<@84}w{Rh7PiWxFe7QZD* zyCV8I<=T+%U*L{EB}xQVa)M+qs;;ta365%I`0IY_QpKL-f$v`LMKj_2(JKmv44+S7 zvyQ#Ix_*42`!*=zPlvD!g_Qg|W-OCxmHm+HP)k7n$^2EE zU(?VZ_1ZeM1!$c&<1~?kpHlfVRE&Ivia~b0%g8>z13BZ!Z$&v&cE=}|U+=L?vbG<4 zk@40ZNYpC=$+%5S-MU$Shvm8mKDwh%Xn$L&|If0-zdHo=AJG0QLj2e6ec=D9==P^c zFDBaYS$yO8FAaPi!H8&Y=ISiG!kB12#a=M28TH>qH%2x_ZrbX+I?MidKkP%Xmr8fF8STl*K-jVf?Rx z+{5pJoVycVWUx078LXZygN?VDH7E|=c>kA~-qEhf0f;|U%^+`+#p6$Keg6_%zRz#` zul4qyleG#)CRRrO(YjBU8v-ae; zTwg9}K68!dp(5h3zP^0}IUNTCT|Q!TmD&2G!dRCXC>I)O`^yY-D!;_}klThG@c6#J ziiD|5%dfT$5kH^+gkKj=nop=d01-53Sa4`?Zd#!Qn$)e}WAKxxwnDLaKu*{)T8U;NqTD%*Cr0#W6G4OhgGl!xoD2W~Bw=+n& zfI^}DJxxb+-AhAIR%C&RV3yepqlmeLTO)MS=&Zu&a*=w0pTzh}<3giktlGS+%D8)- zAuS4q243n3bA$9bPU(G@rzZ6}CbKL7p;Y;Ikba+{s3<8#*Uvxs_d_E8^C|kf0ZPHf z((K>nfb&01$v+JiekxcQ%$QrqdabN;os_3)!l4JGbY zBqHk_P<6(sUUGWmgYm}L$?7O#*QW^tOpiYqZW391QC-5w#z?s9W}USRY?4rdT6ud7bGTJM?Fn3V%BGasR5cp^yD5TOmFW>$4q?CdI#GKq+ z=iUYUZkd|qorakhy5%(6xPtAaY3+!ao5#iin>L(~MPd(IU@d>-B?VC zBgyy}4vHrF8RsJe&<|NY(~qg`1eqnf%3~U-^KUp#X@{JZ-d#pK9##&@PH1iupha?8 zr;V?FUaK5w4JZcsM4jj_QUAMRM~ZfOPDXb2M*p0>&R70NQ3m_|e1qHOXRs!6T%4fB zxlhnRfLC4&QB4*=dAYKkT18XS>B>3(5}N{U3XdXV_@^?0(Tv!DJr=Vgj8;{lCyY^9 z=XoWuv7I}JTLmbwt)AZU%gbkdVfW!YvXDlN+vaE z1BbhCS<|)4KvzSW%u)!N{6m@dnQ89CFWhQGIj2nm&w0zSRgi>Dg~tBfdoPrW2~`ZY zRns}1xL{%=|0RIN630UCPaiH>Q=wcZ4lT7tr}D0o_qO}3-s)G}aVliwRT`l6BYcg8 z_St20F57z>R>wh5L}g<(q4(5lh}z=9_G;3#rLmTl$C3;^o|BthO%!8`hN>1oDE?}{ zb#|^flS0?IX#6U6+A&QpNH+^@_y=hvFhiVBTy9YbmWq3JA7er$6Ml!6(llsS`FmMA zL1G``6VZZGD_ggqFJ=IQRwgZFDy^rtHfiyV*pK+-{af zTPO=mi3UCoqw6YVUM9&L_a zo4F_xjrI{m#NQnR*-YRzB}V{9_-_C;jkmt;VMGAmU$f)Vv~_wG|w+r(LpJgO+ii%gb z^cDDJ-^6(tUz;wx-{zRi;T^;V3WX!3Chng8n9Ih5Eck>dFXpz9Jt7`|8X?Iqv6>43 zQgS<__>svpmW*Pa#OE1Z(mZd+VWF&fRCc+OLCTdZB1A&AP{W1jsDO+!qLEBl&?jTk zw(s!jcyJ3tphWS;g{CLWk3??pZUK4mCj_s~f)HjKFa9GrYTT#WuFcoGYit>{QJ*55v(ZM~3dWw7T+7uk>LVLA! zUqs_O^tEd?hbQKcJyumR8Qo~E;K98{Rq9RyCz)&kk4QERV)DrysVAU_5nFfs$z8uT zuh?ru>!Hym^2#kZ7ZlGCh*#oD_V}ReBNhj25A2i&7T#7>KhBc&ekO`7$C6x2aauox zLQL2XJ~=q6*~^I?g>Nv0t+jWKl2k{MW^T=tRMJS&jrX&8E$sovD|x?~=eQyl#7IJS zMNJ`v5~~UA0J1GgN&xU_att2YGbpzSqIelOJF^tEMf}qQ>(lI##E{qc$rl%z2`*|+ zL+;}8yoG=*lXqC`7iR0}O)C`GbtA8%S-;}JY2Ik1g2+AFk?pG?vljCHplIYXDOk_5 zh?_Ikl)#pCO>^lwQ{g#lm5QjL()VV2^Vogh4vI=C@8_+Jzm(ctQTXwqL{vEtB;}RxsSvYzP`?pD@*$!MNC-r8Wn~q8Q}XY( z6~Wf1njZj>g~!UC8=zl-H?0?1VOgRnZ)e{fW0Q7kk>OnVdCIds8~&C5pz}eA1>AZp zjh%G(=f%d$#mC3n=MzkmJRgW&)y^t`19S}?wpwaG4ca=$qpNm{je-kMG)7Lxi))yN z`;M;dS}lbSmrq6Q?$(B$g^-}Zn;e>?jxOoKG?13j$t}c%4A#-(`!P=zNk%DDh!lcF zf0}#5t{bw>SqCpxN;3`QE-piWKIEBlrKI$9g-W1e&~44?rCbt*X75-OF}w5iG!%;L zLT4yBm9U_QErp^{rN+iCqy{3CiYw*}9vFy=nBHq0=qssV7FUOPOK#K;*UF5! zk7TyR7@&V73(|V#k=0}_WDN-ko$cJ)8G;GxaYjO-i|!`+dAL$M6sAg)oHwOleXFR7 zt>`Svr^aq}jV#8w+=nb_M2F~P_xY#bH)ma?%@s)z=UgeF5KH74P)bP-LSOHg%lmsP z4UdmXjrE}P*_XHbU$oIJ(*w>mWh97FD~Uha+^S)1vBOCg41jv8Xs6P0QjabjoxW#Cr-%-> z3@3<99X0J;3+B-4>B6w2EcuN~%Q>2NMR{sZalla;=2bFY!8K*HeU(z~k1ZB$%g6(B zy|JsL(b(w?ZxS0EC$a7>hbHVm#`ZR2Qo{}}HqKRDGv0Ap<10X@vaCZY1_@W%i&d&Q zRy$OSVkdaJ=xcObGt$RuP~doIQ(CW^kQO`{F1;#nG|0J{Q>iW$=fC_RxkiY;RL_ti zN|DztLvZ#31Y-L{Y2u7Nbh-ocY9J>{r#2uSY z9z1hpV}s^N(^?m<#NqS|fIb3i?}-N~a@&oFtzw4bwO(@6VKm)&tq%ZX5sQ%C%y^{_ z$vI}r>8C=Y6I#1&D<^I}?ZUkOV@KK^EdA*TGs621c>##lp*(rUDc)pf;c&zgq}3{vUy0|JM2=(g zFvI&$mxGD$XL?GK^Csfsy8D!TuvZkb24PtVL45B;Y^1}GuS%~G2VH3tL$*Xl{lcx-|&9OQ1n>(aC(56rv<`tN* z538vi_sh;{JW5P#&Rn57-s0?9?2?F(zl<792^~<~9e~yl82vyAlUrSiD{3?m%13o+ zmyL`QmlY@unMJNRfYXr1)7pgAYV*@9G8w)2>SX}0-51$~*O|)nb#UA+A^$LyIBRAl z(BoJl$T}^n5WkK=UCTRnYjOstH}ber!`cp#TD!YExiptS<;@$_`GFtJ4BSIh?3iHs z3TYT7<$Fq=2MU~V5v3S&_`*8?jrx=c+E^F;t%Wx+tfN5;VfdD|Gy6|qTU@&)9r`_8 z_P&bxSgjy%B2LDxAQ7)d-5|EPVh>aVFO%N>m!7SdYa;DYS>U`**Av@5}W}7mcC@JxJskk35#V}g5;MQEclvM1TDlS#7idT*3goTgjwmO@gt^pMA30$_7ZhY^tH{Dmmn62Niz z@B~EwR-osUGW}@bIeccAuEmdyFY(;-Z?)qBL@Ge=TXc}~3cG64N5Z_tMxaSSM52ll z2_n(-$Y_Ow61Ny|x`=T4B(*~*co65?pzGc12 zATyXzBr}Cero7KfjwIBI4&+IYUDw>Yd%sSNqARWV(2pM?&rk``P2lT#=AU?QyjT^1 z?CT+nKs4&koJ+>UwTf$8fvRzoS7=Ud28tZpl2n&Nx$%SP22jaB8DIF6)-5AmH@DH8 zatEzxE?OIc%^jz;*gaV19VNj!WC%A1q5P=d&*!C9RXm^gyf&yTMSm>#k1InDH%cNt zqNA923^5FQwNy<*HX1RFQk6ixs7J?se>$4*aIUxefl0F<8FpiTcfq$P`W=7y+0BhIbBJ7|O=#CANj{*T zMaJ?6q;UY&>Xp#)Uo>p2pb}KTBbmPH^^MKTE^I-wwTyLbIGv7$y<6<~;lF33x~Ny7G0=~8qG zUs(ZY%-Us>dBoq!VsSKQg-=bRQCnMZf8CCM={%iu#{O<-r%oE`u;WBon((MX0~l!g zW67vlUGFf28y#r~rMU+{Ei8*E*S;jqt(4f|LN!fTdFhNx{e0IftU)vIN_OHLs~FHu z;Cg=>m8&Lnt6M2um{-Ja&4cMwypdPl6_LY!#@dtdnA0a^UU0^kfMV{Kvmu8WbO#D% zCk&1U=kpaO8Pr7|nFrd)6N_YCeau3#J7>k#W;cTeobsic-VL^@#6#*M(1^j)Wtvbz zM7rVK1T)75QyqTcv`C@o1wMkzmI<0*fbSteueH!+o&er~!dMZn1*Mw^=y7dTs=uT5 zdG%Vk^RQi@qlAj;HnGe)aVB;Z-PbBQWYs2WtsMXCsh&j`YG{AdjCEDo+6<9iGW-ZpPE zS=B^biu$$$4`dmHolR^OsyCuL$I+;)$%^{6a=N25?aYb0)9k#(ea3pGUKffgXj|a% zgy|7bRnR+_V3je_?GhKXT{{>u5E-#JO2`-L%zfUV@#}KDG$W&W{ib+gT7#_Lo;eYt&K^bhfSek27hE=V`9Nv3jOmK79$WMU-fk?aLI5 z;`P6JeMu6zk$~~UEPY~J>PoE+ALw^``c&P+?Sfx%4n*#Nc!b$J3$=B73ZlOu>fMe$ z24#N3`klOe{)*%j@WHqHsxUtJkq5KoxxoKQyJGsTV#W3G-3sv|l_mW{D|LL* zROO1riifxKXK14Zj8CyRuXj(x#*8%e>MF#A8&Mmlm3K)K41RODV?!ECm;>yp*%G~L zzFi6^qsh#uSr7{{Cs+p+>-LqrPwYlf%OnA|R`ItQ-NI;@Yl)+2mk;QtOukV8(iiIds+{A7re^D)6Y{vwnNS@QVQw8tTr{V zrDIXKS0OM@?p~cl4U8s4J7pNqUmPnvjv)Z!6gG1^?LjS5ouRqy@qOL}08U^=x-CceE=swQ*l=GAY(Y}uq5z2UOofOjIszGF z*+*pA(*gKkQXUK#*Wm_t$aLgsnDxr=m_;&S*eLd#pNJJScr7SGd*;pKjH}}zHMyOJ zmtugPxTB+-QgWigJs;8t&w#aVv0Asy#y@HuM1Sl~(6_GE%PF&JwT_*S?+RspcZxQb z!N%blJT<_mUG>1K>*EW9p*VM?6z7l+Q)g7bNXT_65_6fC_NI!gs3f?@XPFJ#4iqu$ zrhU$;94eT+_zI2kCQJ65D+>Ls7(J+(04~AD@#1wN|B{`BX}7a05wV32Z0z^v90+ zeXwc?eYK>0=zfY$+0?aAJB##^y1#0%6q=k>hH5S~yhS}RK>;<|NnJcag%<6CMPm@m z${Rs8H$}_}z;qrrF^l=Qe(VB4gDGvuN&W7Q@EMA2?0rO&nw!d6&Rc7f(u=I+ymatt zJ&P?E+KzMvVaK?DJ{B%v!%grG4v)mzXeHvq)zeO^d-YOxV#te&Jl7CwXy7ADbu2HL z)0IeH?<@TkxJ)SbtJxLVhxgK?MjyZi1?+XBP|8QBv(JYx*RUsT#*Qa^py8rEtDY+s zRUtRH3@6o{*33M8%UuNHk;I9bK6>tZLB+fRQc zFE(Rf+Rfp=eA&eNtHQ?L9eDm-*!b7zV!gbS%_jV~+t^m_#=T3c!?O3a&5coBX+c_Ao8(Dg<|96mS6*TFb`=)WY) zQjnA|atJ*nxN54NfqISvFUbW2FL8icjh!Da7GBG}+!L8tdouFW6UJBHm$q_pu?Vk; zD!=L^y^cZBB!h5~@?k@p&o(rhhB++mSNKo~m_f)9?U}G$HFF@F9U;D{C$ofOcdMsw zuRtp>Y7T;?Q@N*;tPz!>yIqGQ&9QA*0IQ?Dg8D%|7N2CAVdIr=qu_2Ut zpCCt5$ShPIK`1ZZODf#Y2hJ)bDkPG5d?w#MtsIZYOU#P|`pS8ntQs6iF`#Yj2x6h46e#g?d1@<4w8V{zI<&WSDhg zcyTfYj+FL+Hu-+Jk`XB@X99DamUUcn_f`bjtxvLU5=?$-R*1iSk8G>WuAcKWve-P_ zw9A$+RkpwY%p*oZ%JwLEN`Io1HJNd+d7J}a+2zjwU001|rJR(U@4`BVjm_o*L=Ftl zO1+~g1FR_21{5SRXT|P=RB;ZpfJcbTPKT99QEt|TC|tq` zG9>jBR3t~U-t-m1ktZwqYMNDjR)V(2ncb%GTU~8Yo?(B%-(l;0eJK6ddHkIIqZ@}W zN-P+K^(UX)Lekp0g%qd}J4>M?oXEV2Z!Vob!0bc(I5Vu&5MJYHcj#Rx-9v9njxj2F zHR99M&;jZZ12Bn7bWFz*lOj)aQR7e3Yk~MNx5&KPkZaBKWZt%m&^}Lniy@L^+@9LO zv~&Cbdt>VkASXcavwC4%W@IvX?tA*;8_?~#A^hiCv=Y|KMJp|XY3Vnhmh?3 zDdVr7>dn>GjQ5E1AqeYW7;@;So+%+e?A#wYBe;TCSDE-^o(0vQ45gn$ z%FCmUbgM%red4ov^JkFi=e_;O&1ZYD>MuvW|E{>^&pEUIPYyA^)zNbB@6u3~{aJop&^b&49p{wgPX#HrpSD3rFU44DHUA`p3IV8^qz90R( zx?voxR7w)KlCw;VCKK+An`6o8mAt&}fOLMvc6j3EVo=5%)abv4j8%*_ z?lnNm!mpf3&|#N_jW8UtfE9915x}OmO)w~RU0yJc-BL~ny~j-l)eicNg>f_;Cs$5 z3E*sIid7vUk!RY2_HHlE0#K{lTa&W8VgQMop~T*B^YhfE?Vi%UA~+5x6drxzx+CWw zJc1;5kSwJTU}MlIHeW0*z1CuAkVxjrAT}9zh!kw_p;nS|yH5};mWqFJCI&@wTphX+ z>pxbt@V5biP2o#hV6rw;TxMdwQzx@3+1ixIxypA6<`PsV6~i5F z=~#kY!kR&!U^j`0I@e2bz!f&t3Cl^gge_R@oqK5ahj$AcIAd7)X?H>0{Jl$tcT4gV zO4_rp+X$?|SHS-5!Zt|{s+@i%f}yRqx?E>dlvm84^=#8gA=6$A(d-z&JTDMjED}Be zXE*K^_-#f3T6B_LmAngiZ;A(9{zIFfHusC)jo3LR|s$>~3@LAbv>qU?Wf$mSn1uKsoiU6lDd zF!zbJN|>{d?BWmomINo+|fnoPMi%L_8F4mQ1oc~M1XM;pj?-1~mDbpf?1 zVucxohr_T}Zm241B?u2H5qE^qa!(A%_#7ecg9f}8vR~ZL4aT<7-8{3N-!O0SY9^Iv z35Z!#gf0zahPNu0$<@!X5 zOoX~mG&Q7mVrbeG#gycx*Y-_{{qn=U0B+s2__koZ$ zWfb4=wYGI zkOxb?7-&_lrznilQt>nUUAcf)9kyoz%DuB3tV7wVPhD9dq#- zKHoT*Oih?_NQF}LuD{O`8$F(aaVwUBo1kuX!Dt;>V3M2bGPpOiJzt>Uk7aqtGA3l;-G*H(m- zK@7ZVCS&>syh(19o$QEaD{IxKVx9A}(_2QZA^-jN+XR$!fWC1T*W3}EcW~_XU@l5s zI|_W#031q)k+-wMw_S9Hv@r?QCsU(+2|WwuB%x~0DMfvSgCzJ5AsX@e=bQhCq94GeKNWZc(35Ezo8d{bbD#bWM6SA!)sIDmN35HD|3%*NFV2>ZtusI zHrE2yBDQtAEA}MShv!=D))YM2j)~xzSbd;uQG;w|3g*@sNTwfsyY`LXt$o$M)MOUV z|0FND&>h9FnUO^E^ONRISJ}1h!nY;L8M?5n9tRz1cS1{i)YSK;2s4M z4QBHZYli22OWtMF-?^zwp^<}}B6d>`_ulB=OY|7dRH>l{5a?DK5kF903QleQ%l3!i zRUPvr1YwT^m_Yj$%5Il4ircB)h^~3bW$#^!J=L#umjE~ZRoBjWeIVozwa)H49Xxjs zgS99kM_~BRudP3C$ME)Lx5eOq{uN|!4BFbtT0Z&G2lu++L=rq&v~Qb!w@U_%1)4Ha zT_{67g?0tMrd=T1qSEQf^9!wlPM7JQ7sSKot9OeqTF%Q?3tEiiMv^&GqB@d1x+*J6 zTZ1C}QCE{JL9~1~ojCx2Ku=W{u+U`wrhHD)B04unr;3V>ZT@FG0;U)0$Rgr}K|v!k zmi3f`0g2$7 zbjN(w*pPixUym^o568QG}t=ExO`F7m6|f!GN?>d zHGKmj36;P?j0~VYQyuKW*baskd(POr{s?CQw#}w+Zh@21qrC6Y zh3E!*)*w&SjQXb6%wOa6Lj%gVG8+$pdUVk1mIJXC&I1}1xcFE>9HESG& z*ko!zCb^+7n8@|Ag4=2JxY~g@(ej&Alw;h!Ak=Ftini_=?hL_?p|ga(Jt!mu_J6zI zu^zKV1t!WPs70^H9=mu_cu0X8bsaO-<|0uJshOL|sOSzBD6_vr1DwVOc6E3c2j1M# z>G1FA2jPsz8s6h#04q?{p*U^+I$hs%Q5P9bWjnxA`6*m;rZk@nz81t3w(VmB!x|DT zjm7gGtJ@e((&OD5L1x+-vz*sNsZr{`gF<53WRE4#>#vGT1S*_r1d9j#(bZKb620jm zU0Bn#7;=Ip*BGmI#~eU{KB;x+ZgpU0jTFa{)|c2iNLXz=VD?DQuxj+A)wO4Js zCbP&LJ+h%UKfPgAh~JiblI!o`l~Mn0g}5j5MbYWZZmmUZC9@4ZrJO&r2Yt$&Fd$CX56&^dNnKevR=mv_ z%=grF;p6Id9ru6`R9WBPO;|SF3 ziiO;D)w$0Ybj1E+lAUEp#?N;40FLz$a`%-ol|wvT%*SsSVWYI2!t;O$JWvs z{k2mvo}@5w^>B2WZMv~INo7SrfjOl`Ja@6XG-qu{?si_#<0xr)rL z$E=Pl=5|6OQ&?nZ$tWYUX#j335R~zV`NY@REGFO2&-BE9E3;Uuvx1jPU|BounsBQ+~%Mn#og_XR-D+S(}pSsxQ-7mf32~NS#WJw$F=CWifjnU+xu#x~2Sv z1=-h-;Y<*zOS2=@)!*KZB;wW~u}sIx>q0oKGT)Kjw9z4$NRx$C(h z-#Za&n%Rl#Cqh>{!_ksprlY75IFbh*|Dw(-eV+UycSkU;r@nlYVG}$)Bk`%hUn^l- zd0&_=cu1gGGzXiWhhj6U^6-MVD6WpNxiX@ec~hNaW3K{x*QW%|+gZa-fLnpxZ@@`= zX(!&F66&J#XYqqSrunF%I%E|9cDnaqiZ;C5He4_s@Cm`-EY~|FF{4Q^=6^NI)*WP3 ziS@XW)}a ziYwo4ro_Kx{Fi$qDOtv=TteU4Mvj{Dq}6$xO$$Y+fTX?!DV?}I1gY5R#jPceUGMRv zKK0!X!VK_*El$FSN__LW*UgAzFJX<$CR1x%%XmP}q@+WXMZ|CX=0jL$vBo1q8tM`+ ziuhVjx&O15OSU&h5~E^IFmT1qVP@q}Ks_>KQGFs!$(JD5I)b1I1t4AlmP2%II$96L z#Dn5R*CIPnz0?Pz9d&{_cz=d5s&0WKdgh`?^>Kv_S^Q9$(u$|u7@3y`u!;8wf`%Rl z2^e0vMVNzQzKfefLHq#&g6oQi!a zXPx^{f4uQ*DfC6mfB5x@eSUL#{wTb+BBhGm2n5M~uLsqzybYtN@Y9o7Af%d3_>wPR zrt}+IzHx1#1Ot zzavaZ+36@Zfxif>R~+%1s{*uIj|8cYitIc)Q+V?9t(x*vkCZEj-1MI!x?f!iV9e#+xVPTX+e?CIfhq@L(!cYybF?Vlx)JL(JU z399I6Hw%|dt4#uaYi~hD*(48DQ!_6dZ;dP@PW>K!UsP;B0%`e1O)^G`I;Qh(ZzyQC zu^S^?YOoE`so^fH(6|h`PEdPu3re=T;L%?apR=hCnXHUlT5gGHBdah(dX*aH=u`ZG zEkDVZT%2kfyvfto7`1UoIo?Rr-@mA|`{KMxba2N8f*@eWO# zv^J39+?hm`||=U9*Lu=y;>Y#=ak31Atox`mt-wQwK*+BcD$tPt&Ag zPJCLM6@KjsO*bvrzjX z$FujLp|=?pqg|OW>_$5Yk<|hvdQ#IOBK1JC3RWqzKV6S$l5rgn*RC7l*)37SHI9lO zpOswRU^iq?K(azFony01m_;A;h8p@c(q}liz~>T}{Z-s$#LzEIjtiv!(VM?c=3YcNH2x zCAA1Ho%Du0ZL)R4Ad;?ZfTd*>*lq25rzNnKGo~!Nr4=m{t(2nW3}uCU&?b>+BRG6L zzuWbFJ3cOKZT&Pal4puFHVn|vOxNT(8$7xzrDd%!pjYw=^$pWY{?6vha3<)DgfKra zsp?5XfygH`ZWI}I`zw{l3vN*#mu{i9U$vJg{v$>Ii08D@7a`;vfl=}+;dv7{FeQjl z7%!)dCuQ}EyK_?v?1V|ciC!j6Zw3eyGS4c#kHJSk7~_aA4NDg*LYdnVZj(`c zf82o5KBpA#4;f@XC(s12q)lOIfDtpHP9Z%)ASKxVCpx#dOZ<=GaGPti-M3MT1qmaH zl;ywwZ;Qoec{PmpQgFms)08#FtGGv`YJ`_D_)Cx&;hgjcyg>a~4iIDJtwP)`Af-CQ z*_b3P8?c+!2g$yFt+shp@Xw^xN=KEIjCy&Uys!Wx%BMwLnE1{fsi;-0XkBk#%(Z2; zq1p$riB4Q3*9Hyod>jIP?rqCzqnD$|7A*H_BkaItCq)gnAFs+dJuE&VN`m=Zl30`6 z#wsY6OY(To&@Kz{q?|N3kKPA9)MN)D=rx0IYSuPDf!c@*(NwAn8u``Th9H8o5G{0r zUzj*olz7LNxi+8;n0OPqynpu!apHjf!EJz~TE9lUzWE9}C9-}rd_Q^5Fm84jKX)hx zwZJuUs8ZiBli$Hcd5gWAex#Urq+T;`zQN{(zu{t=jy_m}5m7fpADs;#uO^w@*7agAV*v`n&Od^e7`L&{ zGOv}cY~Cfhppea0dv&gS8S8N77QG{REl5#K)11PcP^0D?2Vhs|w2QWbPo0fGfR*;$&Uzu3ejHU~ zi^_bHE|_r~&DpwLQq8*U+2<$BB}x2*WZi-vCbZJKKx1Fzwfb9lly2J}Niu_TAPra* z-8ezO=+-zN?3+A^C+jPrIjq1qXZyC2*QwM+o+V`2!9`uilK6FA&Z|ZN+*{+PP&X*Y zI&EMkB3*c9EEI?ImO?0wiE1S?HNLGHY2S1@{N@~fs}2Hf%VHy@tvCJVtIhhB-ZLS+ zQzf?`O1Qf!Fot=R&ufJZ(i|@ac*fR3>WnEsOET}af#E804=Cj9eWB@Ob&-9nPQ||_EUC1PqX4RJs!|ijDZ)~MEbJb+TSrk@8Tj^cekhoEM zkk@zkjrjdxdyV!4|LIwWEwDt6f6}N7e)(|t2?c57t6q`VZ7I=q3?7MIL0HNJzE*{3 zS5qt!!r$9`W|{oV0cx+O<)|A>~)Hcfs2PVTpT0 z0kxR3fC`sLx`K0$GL1!oBXnwKc&bD_hxxy9K0dkd7g(b0#$fkZr2Q+Bp$&!b7ha<6 zs9<*nr2TH$@E2&J?aE;HTBQB29K;)he>0T*uLQ)KS^L!Ie{OqQ!jDW>bgRYPa<&^h zw@J_V`P)0YXjh=G(jSODEBt|=>lDA%OUo?$D4ISf+RbzK#@A2WBcH)zm%c+#ni(7# zp6T*8d+%Vcc!WC$ZVj&_x|nln^qD_fu6 zK-o*Bhg!_a{X!papf&s;0YA{^fF7G!@e z4v49(MBql-QtJrt!GB`>{jIOPwd`&1kYX=PoVN84{T>nuue?JjF=E7>*S*OH=8g<7 zUyMmR-Y%xz1llUX;C`4Z;t7i~-k?Dx(qw*nN|0xq27CNXo$+y?jSV!LdkG8bSp$a2o`B z0yyyd3%t~cFlb%rCv_LF9g+{scH*O6Tka$iij_UpeDUg->YI?o17%YLTAY4G63vbK zr*rNN);ZC~KGi*J>falwJ;#;pPY_F>M;*pT-`&Lz5kUeVEKmMbPvFO87=tulV%cTL z0bC!%sim+!VjoJ@QwotrJ+PCr!CmAp)HY=SwCmyqi85=7WIhp-S(UYqcl%dK0;r!k ziT;y!^H*g8(6C43$MfQ}inw7|A6(OO6h`&jaL`97PFaRQq<7=2JcWMgZd|hqm3ryg zK5QQd`gs}$s(Ca~^$Qky@6#!|K3ah2Mg zON#}&yQ(?6MD{C^F{_|x4b~pGttL|cUbvDWMuGP}r~@Hv%7ITkroqG_X`Vr+;AMPC z&>=u6Zqz^c-WyU9fe@~7CKpf2kEHc!hR#fO-P$;J${JtG*faD(v2(RugJzM?#ePrvTL$bMBkwTV(AwVyoU8eeJ1!H2glj6~1x%b4 zB&HGZ%FJOdD%hs5944dAj362V}0!9LYuu;BG z*Fd_oo#ipwN-IbD6-S9q$yBS-w-Zy;@}1Q477x?PHjS8?zb%<7%=TuN+ol9it z!%?4DvjbWpkCL|oL-pjpm+2zS@qsnmZ3| zsl88356bdcZ@|;LZNq>N9b2w~&cne#6aE>8}4bEbhEtRGC0j z#W$|zp3mw(9yne`RH zTjU3JXHj4j;gR7M@Sf_f@sm+?&k#4P@!lwLrfSaJcG-2P5vlH;pU zz7$94;+eTXtEeeLKf|3*g#n}c7J@ioGoXl%R??vBo=g#};F06rO}&uR8}58WlCTGy za4dy(mSgM8r{R2;McUyhkG922Ht;Nqx|TCu5N4KfdRC6imGf4RS}OjSkn&1BW=A3z z+l}=JH!?sO$BwdiX zdz~m21jDqHz~8^Ae~6TxCXHsg?89|{A8f0@j^Z0M(O34DNh0*=FIPfSxlUINuKU^f zk-z6{({b_Q6Ru8j#~jAYVF$lPjV)6H$LpnpH5PRo2(C1p~LF9IoX3mA;|Zj1KW^3E$yY>Uk!$>zORw2B2I=CxxXuS(cth zHnNo*76fJ%yrMwILix6@IhC}jH}EJdVYpo>PS^2xnhE=_!E`zsHK1o)Dd-9;wfyeBRM73yPOWdjFGdNdi_TRdPOI-@Sc;{94PM7%oe zXB37FkY++PjY`au&Vn@ySILvllI|?WT#nqU(~AzS9Hwkjiw@-(!gSY3>cdxp?nN`& zLu10%LqXYfVM5x*NZdnV0{>^F=J}7h=NW+h_ed4Eq=%4I7@GMr~^3=D_`o z^m|odYB+x%mKM#-FeELmG@|j=xgKaGLTi(7z`a=`d?iZEy|QeOX9&4VAu9$U%5#$p z`_`f!HWy9qwaa{DMGU5gDCJ;h82VGTYRGPgnwNM+S+!nG3gaS4)*;}3qPmEvB(igF8TaS#djeLZG^Vfb@5eCSctm-Ip$NoX1J!d7iOt-iXpCX9(%;+QBnu_hW8)v zj6@D;uoF9|EI3wOd*95ywUYhOhkJrB3MAJ77So7Q$>PovMEo!eMUdfxTb|$;X*$3c z)E$L^OsMygAY82#?n-%>jUfs4EaAP2i5cz!)`|#$rZ!`MqjgAZq&dLPjasQ_58yss7)%Q znol^P+rP7Qq8$#$l5C@L≥T}T#{|H#R>|zA~W5^jI?g!2RSx-`;O3i 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 ex + set_state(false, nil, ex) + end + elsif incomplete? + raise IllegalOperationError, 'Recursive call to #value during evaluation of the Delay' + end + end + if @do_nothing_on_deref + @value + else + apply_deref_options(@value) + end + end + end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. If the delayed operation + # raised an exception, this method will raise that exception (even when) + # the operation has already been executed). + # + # @param [Numeric] timeout the maximum number of seconds to wait + # @return [Object] the current value of the object + # @raise [Exception] when `#rejected?` raises `#reason` + # + # @!macro delay_note_regarding_blocking + def value!(timeout = nil) + if @executor + super + else + result = value + raise @reason if @reason + result + end + end + + # Return the value this object represents after applying the options + # specified by the `#set_deref_options` method. + # + # @param [Integer] timeout (nil) the maximum number of seconds to wait for + # the value to be computed. When `nil` the caller will block indefinitely. + # + # @return [Object] self + # + # @!macro delay_note_regarding_blocking + def wait(timeout = nil) + if @executor + execute_task_once + super(timeout) + else + value + end + self + end + + # Reconfigures the block returning the value if still `#incomplete?` + # + # @yield the delayed operation to perform + # @return [true, false] if success + def reconfigure(&block) + synchronize do + raise ArgumentError.new('no block given') unless block_given? + unless @evaluation_started + @task = block + true + else + false + end + end + end + + protected + + def ns_initialize(opts, &block) + init_obligation + set_deref_options(opts) + @executor = opts[:executor] + + @task = block + @state = :pending + @evaluation_started = false + end + + private + + # @!visibility private + def execute_task_once # :nodoc: + # this function has been optimized for performance and + # should not be modified without running new benchmarks + execute = task = nil + synchronize do + execute = @evaluation_started = true unless @evaluation_started + task = @task + end + + if execute + executor = Options.executor_from_options(executor: @executor) + executor.post do + begin + result = task.call + success = true + rescue => ex + reason = ex + end + synchronize do + set_state(success, result, reason) + event.set + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/errors.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/errors.rb new file mode 100644 index 0000000000000..74f1fc3ddab9d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/errors.rb @@ -0,0 +1,74 @@ +module Concurrent + + Error = Class.new(StandardError) + + # Raised when errors occur during configuration. + ConfigurationError = Class.new(Error) + + # Raised when an asynchronous operation is cancelled before execution. + CancelledOperationError = Class.new(Error) + + # Raised when a lifecycle method (such as `stop`) is called in an improper + # sequence or when the object is in an inappropriate state. + LifecycleError = Class.new(Error) + + # Raised when an attempt is made to violate an immutability guarantee. + ImmutabilityError = Class.new(Error) + + # Raised when an operation is attempted which is not legal given the + # receiver's current state + IllegalOperationError = Class.new(Error) + + # Raised when an object's methods are called when it has not been + # properly initialized. + InitializationError = Class.new(Error) + + # Raised when an object with a start/stop lifecycle has been started an + # excessive number of times. Often used in conjunction with a restart + # policy or strategy. + MaxRestartFrequencyError = Class.new(Error) + + # Raised when an attempt is made to modify an immutable object + # (such as an `IVar`) after its final state has been set. + class MultipleAssignmentError < Error + attr_reader :inspection_data + + def initialize(message = nil, inspection_data = nil) + @inspection_data = inspection_data + super message + end + + def inspect + format '%s %s>', super[0..-2], @inspection_data.inspect + end + end + + # Raised by an `Executor` when it is unable to process a given task, + # possibly because of a reject policy or other internal error. + RejectedExecutionError = Class.new(Error) + + # Raised when any finite resource, such as a lock counter, exceeds its + # maximum limit/threshold. + ResourceLimitError = Class.new(Error) + + # Raised when an operation times out. + TimeoutError = Class.new(Error) + + # Aggregates multiple exceptions. + class MultipleErrors < Error + attr_reader :errors + + def initialize(errors, message = "#{errors.size} errors") + @errors = errors + super [*message, + *errors.map { |e| [format('%s (%s)', e.message, e.class), *e.backtrace] }.flatten(1) + ].join("\n") + end + end + + # @!macro internal_implementation_note + class ConcurrentUpdateError < ThreadError + # frozen pre-allocated backtrace to speed ConcurrentUpdateError + CONC_UP_ERR_BACKTRACE = ['backtrace elided; set verbose to enable'].freeze + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/exchanger.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/exchanger.rb new file mode 100644 index 0000000000000..a5405d252283e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/exchanger.rb @@ -0,0 +1,353 @@ +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/maybe' +require 'concurrent/atomic/atomic_reference' +require 'concurrent/atomic/count_down_latch' +require 'concurrent/utility/engine' +require 'concurrent/utility/monotonic_time' + +module Concurrent + + # @!macro exchanger + # + # A synchronization point at which threads can pair and swap elements within + # pairs. Each thread presents some object on entry to the exchange method, + # matches with a partner thread, and receives its partner's object on return. + # + # @!macro thread_safe_variable_comparison + # + # This implementation is very simple, using only a single slot for each + # exchanger (unlike more advanced implementations which use an "arena"). + # This approach will work perfectly fine when there are only a few threads + # accessing a single `Exchanger`. Beyond a handful of threads the performance + # will degrade rapidly due to contention on the single slot, but the algorithm + # will remain correct. + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html java.util.concurrent.Exchanger + # @example + # + # exchanger = Concurrent::Exchanger.new + # + # threads = [ + # Thread.new { puts "first: " << exchanger.exchange('foo', 1) }, #=> "first: bar" + # Thread.new { puts "second: " << exchanger.exchange('bar', 1) } #=> "second: foo" + # ] + # threads.each {|t| t.join(2) } + + # @!visibility private + class AbstractExchanger < Synchronization::Object + + # @!visibility private + CANCEL = ::Object.new + private_constant :CANCEL + + def initialize + super + end + + # @!macro exchanger_method_do_exchange + # + # Waits for another thread to arrive at this exchange point (unless the + # current thread is interrupted), and then transfers the given object to + # it, receiving its object in return. The timeout value indicates the + # approximate number of seconds the method should block while waiting + # for the exchange. When the timeout value is `nil` the method will + # block indefinitely. + # + # @param [Object] value the value to exchange with another thread + # @param [Numeric, nil] timeout in seconds, `nil` blocks indefinitely + # + # @!macro exchanger_method_exchange + # + # In some edge cases when a `timeout` is given a return value of `nil` may be + # ambiguous. Specifically, if `nil` is a valid value in the exchange it will + # be impossible to tell whether `nil` is the actual return value or if it + # signifies timeout. When `nil` is a valid value in the exchange consider + # using {#exchange!} or {#try_exchange} instead. + # + # @return [Object] the value exchanged by the other thread or `nil` on timeout + def exchange(value, timeout = nil) + (value = do_exchange(value, timeout)) == CANCEL ? nil : value + end + + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_exchange_bang + # + # On timeout a {Concurrent::TimeoutError} exception will be raised. + # + # @return [Object] the value exchanged by the other thread + # @raise [Concurrent::TimeoutError] on timeout + def exchange!(value, timeout = nil) + if (value = do_exchange(value, timeout)) == CANCEL + raise Concurrent::TimeoutError + else + value + end + end + + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_try_exchange + # + # The return value will be a {Concurrent::Maybe} set to `Just` on success or + # `Nothing` on timeout. + # + # @return [Concurrent::Maybe] on success a `Just` maybe will be returned with + # the item exchanged by the other thread as `#value`; on timeout a + # `Nothing` maybe will be returned with {Concurrent::TimeoutError} as `#reason` + # + # @example + # + # exchanger = Concurrent::Exchanger.new + # + # result = exchanger.exchange(:foo, 0.5) + # + # if result.just? + # puts result.value #=> :bar + # else + # puts 'timeout' + # end + def try_exchange(value, timeout = nil) + if (value = do_exchange(value, timeout)) == CANCEL + Concurrent::Maybe.nothing(Concurrent::TimeoutError) + else + Concurrent::Maybe.just(value) + end + end + + private + + # @!macro exchanger_method_do_exchange + # + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + def do_exchange(value, timeout) + raise NotImplementedError + end + end + + # @!macro internal_implementation_note + # @!visibility private + class RubyExchanger < AbstractExchanger + # A simplified version of java.util.concurrent.Exchanger written by + # Doug Lea, Bill Scherer, and Michael Scott with assistance from members + # of JCP JSR-166 Expert Group and released to the public domain. It does + # not include the arena or the multi-processor spin loops. + # http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/concurrent/Exchanger.java + + safe_initialization! + + class Node < Concurrent::Synchronization::Object + attr_atomic :value + safe_initialization! + + def initialize(item) + super() + @Item = item + @Latch = Concurrent::CountDownLatch.new + self.value = nil + end + + def latch + @Latch + end + + def item + @Item + end + end + private_constant :Node + + def initialize + super + end + + private + + attr_atomic(:slot) + + # @!macro exchanger_method_do_exchange + # + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + def do_exchange(value, timeout) + + # ALGORITHM + # + # From the original Java version: + # + # > The basic idea is to maintain a "slot", which is a reference to + # > a Node containing both an Item to offer and a "hole" waiting to + # > get filled in. If an incoming "occupying" thread sees that the + # > slot is null, it CAS'es (compareAndSets) a Node there and waits + # > for another to invoke exchange. That second "fulfilling" thread + # > sees that the slot is non-null, and so CASes it back to null, + # > also exchanging items by CASing the hole, plus waking up the + # > occupying thread if it is blocked. In each case CAS'es may + # > fail because a slot at first appears non-null but is null upon + # > CAS, or vice-versa. So threads may need to retry these + # > actions. + # + # This version: + # + # An exchange occurs between an "occupier" thread and a "fulfiller" thread. + # The "slot" is used to setup this interaction. The first thread in the + # exchange puts itself into the slot (occupies) and waits for a fulfiller. + # The second thread removes the occupier from the slot and attempts to + # perform the exchange. Removing the occupier also frees the slot for + # another occupier/fulfiller pair. + # + # Because the occupier and the fulfiller are operating independently and + # because there may be contention with other threads, any failed operation + # indicates contention. Both the occupier and the fulfiller operate within + # spin loops. Any failed actions along the happy path will cause the thread + # to repeat the loop and try again. + # + # When a timeout value is given the thread must be cognizant of time spent + # in the spin loop. The remaining time is checked every loop. When the time + # runs out the thread will exit. + # + # A "node" is the data structure used to perform the exchange. Only the + # occupier's node is necessary. It's the node used for the exchange. + # Each node has an "item," a "hole" (self), and a "latch." The item is the + # node's initial value. It never changes. It's what the fulfiller returns on + # success. The occupier's hole is where the fulfiller put its item. It's the + # item that the occupier returns on success. The latch is used for synchronization. + # Because a thread may act as either an occupier or fulfiller (or possibly + # both in periods of high contention) every thread creates a node when + # the exchange method is first called. + # + # The following steps occur within the spin loop. If any actions fail + # the thread will loop and try again, so long as there is time remaining. + # If time runs out the thread will return CANCEL. + # + # Check the slot for an occupier: + # + # * If the slot is empty try to occupy + # * If the slot is full try to fulfill + # + # Attempt to occupy: + # + # * Attempt to CAS myself into the slot + # * Go to sleep and wait to be woken by a fulfiller + # * If the sleep is successful then the fulfiller completed its happy path + # - Return the value from my hole (the value given by the fulfiller) + # * When the sleep fails (time ran out) attempt to cancel the operation + # - Attempt to CAS myself out of the hole + # - If successful there is no contention + # - Return CANCEL + # - On failure, I am competing with a fulfiller + # - Attempt to CAS my hole to CANCEL + # - On success + # - Let the fulfiller deal with my cancel + # - Return CANCEL + # - On failure the fulfiller has completed its happy path + # - Return th value from my hole (the fulfiller's value) + # + # Attempt to fulfill: + # + # * Attempt to CAS the occupier out of the slot + # - On failure loop again + # * Attempt to CAS my item into the occupier's hole + # - On failure the occupier is trying to cancel + # - Loop again + # - On success we are on the happy path + # - Wake the sleeping occupier + # - Return the occupier's item + + value = NULL if value.nil? # The sentinel allows nil to be a valid value + me = Node.new(value) # create my node in case I need to occupy + end_at = Concurrent.monotonic_time + timeout.to_f # The time to give up + + result = loop do + other = slot + if other && compare_and_set_slot(other, nil) + # try to fulfill + if other.compare_and_set_value(nil, value) + # happy path + other.latch.count_down + break other.item + end + elsif other.nil? && compare_and_set_slot(nil, me) + # try to occupy + timeout = end_at - Concurrent.monotonic_time if timeout + if me.latch.wait(timeout) + # happy path + break me.value + else + # attempt to remove myself from the slot + if compare_and_set_slot(me, nil) + break CANCEL + elsif !me.compare_and_set_value(nil, CANCEL) + # I've failed to block the fulfiller + break me.value + end + end + end + break CANCEL if timeout && Concurrent.monotonic_time >= end_at + end + + result == NULL ? nil : result + end + end + + if Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + + # @!macro internal_implementation_note + # @!visibility private + class JavaExchanger < AbstractExchanger + + def initialize + @exchanger = java.util.concurrent.Exchanger.new + end + + private + + # @!macro exchanger_method_do_exchange + # + # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout + def do_exchange(value, timeout) + result = nil + if timeout.nil? + Synchronization::JRuby.sleep_interruptibly do + result = @exchanger.exchange(value) + end + else + Synchronization::JRuby.sleep_interruptibly do + result = @exchanger.exchange(value, 1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS) + end + end + result + rescue java.util.concurrent.TimeoutException + CANCEL + end + end + end + + # @!visibility private + # @!macro internal_implementation_note + ExchangerImplementation = case + when Concurrent.on_jruby? + JavaExchanger + else + RubyExchanger + end + private_constant :ExchangerImplementation + + # @!macro exchanger + class Exchanger < ExchangerImplementation + + # @!method initialize + # Creates exchanger instance + + # @!method exchange(value, timeout = nil) + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_exchange + + # @!method exchange!(value, timeout = nil) + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_exchange_bang + + # @!method try_exchange(value, timeout = nil) + # @!macro exchanger_method_do_exchange + # @!macro exchanger_method_try_exchange + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb new file mode 100644 index 0000000000000..ac429531bf7bf --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb @@ -0,0 +1,131 @@ +require 'concurrent/errors' +require 'concurrent/concern/deprecation' +require 'concurrent/executor/executor_service' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # @!macro abstract_executor_service_public_api + # @!visibility private + class AbstractExecutorService < Synchronization::LockableObject + include ExecutorService + include Concern::Deprecation + + # The set of possible fallback policies that may be set at thread pool creation. + FALLBACK_POLICIES = [:abort, :discard, :caller_runs].freeze + + # @!macro executor_service_attr_reader_fallback_policy + attr_reader :fallback_policy + + attr_reader :name + + # Create a new thread pool. + def initialize(opts = {}, &block) + super(&nil) + synchronize do + @auto_terminate = opts.fetch(:auto_terminate, true) + @name = opts.fetch(:name) if opts.key?(:name) + ns_initialize(opts, &block) + end + end + + def to_s + name ? "#{super[0..-2]} name: #{name}>" : super + end + + # @!macro executor_service_method_shutdown + def shutdown + raise NotImplementedError + end + + # @!macro executor_service_method_kill + def kill + raise NotImplementedError + end + + # @!macro executor_service_method_wait_for_termination + def wait_for_termination(timeout = nil) + raise NotImplementedError + end + + # @!macro executor_service_method_running_question + def running? + synchronize { ns_running? } + end + + # @!macro executor_service_method_shuttingdown_question + def shuttingdown? + synchronize { ns_shuttingdown? } + end + + # @!macro executor_service_method_shutdown_question + def shutdown? + synchronize { ns_shutdown? } + end + + # @!macro executor_service_method_auto_terminate_question + def auto_terminate? + synchronize { @auto_terminate } + end + + # @!macro executor_service_method_auto_terminate_setter + def auto_terminate=(value) + deprecated "Method #auto_terminate= has no effect. Set :auto_terminate option when executor is initialized." + end + + private + + # Returns an action which executes the `fallback_policy` once the queue + # size reaches `max_queue`. The reason for the indirection of an action + # is so that the work can be deferred outside of synchronization. + # + # @param [Array] args the arguments to the task which is being handled. + # + # @!visibility private + def fallback_action(*args) + case fallback_policy + when :abort + lambda { raise RejectedExecutionError } + when :discard + lambda { false } + when :caller_runs + lambda { + begin + yield(*args) + rescue => ex + # let it fail + log DEBUG, ex + end + true + } + else + lambda { fail "Unknown fallback policy #{fallback_policy}" } + end + end + + def ns_execute(*args, &task) + raise NotImplementedError + end + + # @!macro executor_service_method_ns_shutdown_execution + # + # Callback method called when an orderly shutdown has completed. + # The default behavior is to signal all waiting threads. + def ns_shutdown_execution + # do nothing + end + + # @!macro executor_service_method_ns_kill_execution + # + # Callback method called when the executor has been killed. + # The default behavior is to do nothing. + def ns_kill_execution + # do nothing + end + + def ns_auto_terminate? + @auto_terminate + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb new file mode 100644 index 0000000000000..de50ed1791c6a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb @@ -0,0 +1,62 @@ +require 'concurrent/utility/engine' +require 'concurrent/executor/thread_pool_executor' + +module Concurrent + + # A thread pool that dynamically grows and shrinks to fit the current workload. + # New threads are created as needed, existing threads are reused, and threads + # that remain idle for too long are killed and removed from the pool. These + # pools are particularly suited to applications that perform a high volume of + # short-lived tasks. + # + # On creation a `CachedThreadPool` has zero running threads. New threads are + # created on the pool as new operations are `#post`. The size of the pool + # will grow until `#max_length` threads are in the pool or until the number + # of threads exceeds the number of running and pending operations. When a new + # operation is post to the pool the first available idle thread will be tasked + # with the new operation. + # + # Should a thread crash for any reason the thread will immediately be removed + # from the pool. Similarly, threads which remain idle for an extended period + # of time will be killed and reclaimed. Thus these thread pools are very + # efficient at reclaiming unused resources. + # + # The API and behavior of this class are based on Java's `CachedThreadPool` + # + # @!macro thread_pool_options + class CachedThreadPool < ThreadPoolExecutor + + # @!macro cached_thread_pool_method_initialize + # + # Create a new thread pool. + # + # @param [Hash] opts the options defining pool behavior. + # @option opts [Symbol] :fallback_policy (`:abort`) the fallback policy + # + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool-- + def initialize(opts = {}) + defaults = { idletime: DEFAULT_THREAD_IDLETIMEOUT } + overrides = { min_threads: 0, + max_threads: DEFAULT_MAX_POOL_SIZE, + max_queue: DEFAULT_MAX_QUEUE_SIZE } + super(defaults.merge(opts).merge(overrides)) + end + + private + + # @!macro cached_thread_pool_method_initialize + # @!visibility private + def ns_initialize(opts) + super(opts) + if Concurrent.on_jruby? + @max_queue = 0 + @executor = java.util.concurrent.Executors.newCachedThreadPool( + DaemonThreadFactory.new(ns_auto_terminate?)) + @executor.setRejectedExecutionHandler(FALLBACK_POLICY_CLASSES[@fallback_policy].new) + @executor.setKeepAliveTime(opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT), java.util.concurrent.TimeUnit::SECONDS) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/executor_service.rb new file mode 100644 index 0000000000000..7e344919e0e6a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/executor_service.rb @@ -0,0 +1,185 @@ +require 'concurrent/concern/logging' + +module Concurrent + + ################################################################### + + # @!macro executor_service_method_post + # + # Submit a task to the executor for asynchronous processing. + # + # @param [Array] args zero or more arguments to be passed to the task + # + # @yield the asynchronous task to perform + # + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # + # @raise [ArgumentError] if no task is given + + # @!macro executor_service_method_left_shift + # + # Submit a task to the executor for asynchronous processing. + # + # @param [Proc] task the asynchronous task to perform + # + # @return [self] returns itself + + # @!macro executor_service_method_can_overflow_question + # + # Does the task queue have a maximum size? + # + # @return [Boolean] True if the task queue has a maximum size else false. + + # @!macro executor_service_method_serialized_question + # + # Does this executor guarantee serialization of its operations? + # + # @return [Boolean] True if the executor guarantees that all operations + # will be post in the order they are received and no two operations may + # occur simultaneously. Else false. + + ################################################################### + + # @!macro executor_service_public_api + # + # @!method post(*args, &task) + # @!macro executor_service_method_post + # + # @!method <<(task) + # @!macro executor_service_method_left_shift + # + # @!method can_overflow? + # @!macro executor_service_method_can_overflow_question + # + # @!method serialized? + # @!macro executor_service_method_serialized_question + + ################################################################### + + # @!macro executor_service_attr_reader_fallback_policy + # @return [Symbol] The fallback policy in effect. Either `:abort`, `:discard`, or `:caller_runs`. + + # @!macro executor_service_method_shutdown + # + # Begin an orderly shutdown. Tasks already in the queue will be executed, + # but no new tasks will be accepted. Has no additional effect if the + # thread pool is not running. + + # @!macro executor_service_method_kill + # + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + + # @!macro executor_service_method_wait_for_termination + # + # Block until executor shutdown is complete or until `timeout` seconds have + # passed. + # + # @note Does not initiate shutdown or termination. Either `shutdown` or `kill` + # must be called before this method (or on another thread). + # + # @param [Integer] timeout the maximum number of seconds to wait for shutdown to complete + # + # @return [Boolean] `true` if shutdown complete or false on `timeout` + + # @!macro executor_service_method_running_question + # + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + + # @!macro executor_service_method_shuttingdown_question + # + # Is the executor shuttingdown? + # + # @return [Boolean] `true` when not running and not shutdown, else `false` + + # @!macro executor_service_method_shutdown_question + # + # Is the executor shutdown? + # + # @return [Boolean] `true` when shutdown, `false` when shutting down or running + + # @!macro executor_service_method_auto_terminate_question + # + # Is the executor auto-terminate when the application exits? + # + # @return [Boolean] `true` when auto-termination is enabled else `false`. + + # @!macro executor_service_method_auto_terminate_setter + # + # + # Set the auto-terminate behavior for this executor. + # @deprecated Has no effect + # @param [Boolean] value The new auto-terminate value to set for this executor. + # @return [Boolean] `true` when auto-termination is enabled else `false`. + + ################################################################### + + # @!macro abstract_executor_service_public_api + # + # @!macro executor_service_public_api + # + # @!attribute [r] fallback_policy + # @!macro executor_service_attr_reader_fallback_policy + # + # @!method shutdown + # @!macro executor_service_method_shutdown + # + # @!method kill + # @!macro executor_service_method_kill + # + # @!method wait_for_termination(timeout = nil) + # @!macro executor_service_method_wait_for_termination + # + # @!method running? + # @!macro executor_service_method_running_question + # + # @!method shuttingdown? + # @!macro executor_service_method_shuttingdown_question + # + # @!method shutdown? + # @!macro executor_service_method_shutdown_question + # + # @!method auto_terminate? + # @!macro executor_service_method_auto_terminate_question + # + # @!method auto_terminate=(value) + # @!macro executor_service_method_auto_terminate_setter + + ################################################################### + + # @!macro executor_service_public_api + # @!visibility private + module ExecutorService + include Concern::Logging + + # @!macro executor_service_method_post + def post(*args, &task) + raise NotImplementedError + end + + # @!macro executor_service_method_left_shift + def <<(task) + post(&task) + self + end + + # @!macro executor_service_method_can_overflow_question + # + # @note Always returns `false` + def can_overflow? + false + end + + # @!macro executor_service_method_serialized_question + # + # @note Always returns `false` + def serialized? + false + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb new file mode 100644 index 0000000000000..993c3f1e36670 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb @@ -0,0 +1,224 @@ +require 'concurrent/utility/engine' +require 'concurrent/executor/thread_pool_executor' + +module Concurrent + + # @!macro thread_pool_executor_constant_default_max_pool_size + # Default maximum number of threads that will be created in the pool. + + # @!macro thread_pool_executor_constant_default_min_pool_size + # Default minimum number of threads that will be retained in the pool. + + # @!macro thread_pool_executor_constant_default_max_queue_size + # Default maximum number of tasks that may be added to the task queue. + + # @!macro thread_pool_executor_constant_default_thread_timeout + # Default maximum number of seconds a thread in the pool may remain idle + # before being reclaimed. + + # @!macro thread_pool_executor_constant_default_synchronous + # Default value of the :synchronous option. + + # @!macro thread_pool_executor_attr_reader_max_length + # The maximum number of threads that may be created in the pool. + # @return [Integer] The maximum number of threads that may be created in the pool. + + # @!macro thread_pool_executor_attr_reader_min_length + # The minimum number of threads that may be retained in the pool. + # @return [Integer] The minimum number of threads that may be retained in the pool. + + # @!macro thread_pool_executor_attr_reader_largest_length + # The largest number of threads that have been created in the pool since construction. + # @return [Integer] The largest number of threads that have been created in the pool since construction. + + # @!macro thread_pool_executor_attr_reader_scheduled_task_count + # The number of tasks that have been scheduled for execution on the pool since construction. + # @return [Integer] The number of tasks that have been scheduled for execution on the pool since construction. + + # @!macro thread_pool_executor_attr_reader_completed_task_count + # The number of tasks that have been completed by the pool since construction. + # @return [Integer] The number of tasks that have been completed by the pool since construction. + + # @!macro thread_pool_executor_method_active_count + # The number of threads that are actively executing tasks. + # @return [Integer] The number of threads that are actively executing tasks. + + # @!macro thread_pool_executor_attr_reader_idletime + # The number of seconds that a thread may be idle before being reclaimed. + # @return [Integer] The number of seconds that a thread may be idle before being reclaimed. + + # @!macro thread_pool_executor_attr_reader_synchronous + # Whether or not a value of 0 for :max_queue option means the queue must perform direct hand-off or rather unbounded queue. + # @return [true, false] + + # @!macro thread_pool_executor_attr_reader_max_queue + # The maximum number of tasks that may be waiting in the work queue at any one time. + # When the queue size reaches `max_queue` subsequent tasks will be rejected in + # accordance with the configured `fallback_policy`. + # + # @return [Integer] The maximum number of tasks that may be waiting in the work queue at any one time. + # When the queue size reaches `max_queue` subsequent tasks will be rejected in + # accordance with the configured `fallback_policy`. + + # @!macro thread_pool_executor_attr_reader_length + # The number of threads currently in the pool. + # @return [Integer] The number of threads currently in the pool. + + # @!macro thread_pool_executor_attr_reader_queue_length + # The number of tasks in the queue awaiting execution. + # @return [Integer] The number of tasks in the queue awaiting execution. + + # @!macro thread_pool_executor_attr_reader_remaining_capacity + # Number of tasks that may be enqueued before reaching `max_queue` and rejecting + # new tasks. A value of -1 indicates that the queue may grow without bound. + # + # @return [Integer] Number of tasks that may be enqueued before reaching `max_queue` and rejecting + # new tasks. A value of -1 indicates that the queue may grow without bound. + + # @!macro thread_pool_executor_method_prune_pool + # Prune the thread pool of unneeded threads + # + # What is being pruned is controlled by the min_threads and idletime + # parameters passed at pool creation time + # + # This is a no-op on some pool implementation (e.g. the Java one). The Ruby + # pool will auto-prune each time a new job is posted. You will need to call + # this method explicitely in case your application post jobs in bursts (a + # lot of jobs and then nothing for long periods) + + # @!macro thread_pool_executor_public_api + # + # @!macro abstract_executor_service_public_api + # + # @!attribute [r] max_length + # @!macro thread_pool_executor_attr_reader_max_length + # + # @!attribute [r] min_length + # @!macro thread_pool_executor_attr_reader_min_length + # + # @!attribute [r] largest_length + # @!macro thread_pool_executor_attr_reader_largest_length + # + # @!attribute [r] scheduled_task_count + # @!macro thread_pool_executor_attr_reader_scheduled_task_count + # + # @!attribute [r] completed_task_count + # @!macro thread_pool_executor_attr_reader_completed_task_count + # + # @!attribute [r] idletime + # @!macro thread_pool_executor_attr_reader_idletime + # + # @!attribute [r] max_queue + # @!macro thread_pool_executor_attr_reader_max_queue + # + # @!attribute [r] length + # @!macro thread_pool_executor_attr_reader_length + # + # @!attribute [r] queue_length + # @!macro thread_pool_executor_attr_reader_queue_length + # + # @!attribute [r] remaining_capacity + # @!macro thread_pool_executor_attr_reader_remaining_capacity + # + # @!method can_overflow? + # @!macro executor_service_method_can_overflow_question + # + # @!method prune_pool + # @!macro thread_pool_executor_method_prune_pool + + + + + # @!macro thread_pool_options + # + # **Thread Pool Options** + # + # Thread pools support several configuration options: + # + # * `idletime`: The number of seconds that a thread may be idle before being reclaimed. + # * `name`: The name of the executor (optional). Printed in the executor's `#to_s` output and + # a `-worker-` name is given to its threads if supported by used Ruby + # implementation. `` is uniq for each thread. + # * `max_queue`: The maximum number of tasks that may be waiting in the work queue at + # any one time. When the queue size reaches `max_queue` and no new threads can be created, + # subsequent tasks will be rejected in accordance with the configured `fallback_policy`. + # * `auto_terminate`: When true (default), the threads started will be marked as daemon. + # * `fallback_policy`: The policy defining how rejected tasks are handled. + # + # Three fallback policies are supported: + # + # * `:abort`: Raise a `RejectedExecutionError` exception and discard the task. + # * `:discard`: Discard the task and return false. + # * `:caller_runs`: Execute the task on the calling thread. + # + # **Shutting Down Thread Pools** + # + # Killing a thread pool while tasks are still being processed, either by calling + # the `#kill` method or at application exit, will have unpredictable results. There + # is no way for the thread pool to know what resources are being used by the + # in-progress tasks. When those tasks are killed the impact on those resources + # cannot be predicted. The *best* practice is to explicitly shutdown all thread + # pools using the provided methods: + # + # * Call `#shutdown` to initiate an orderly termination of all in-progress tasks + # * Call `#wait_for_termination` with an appropriate timeout interval an allow + # the orderly shutdown to complete + # * Call `#kill` *only when* the thread pool fails to shutdown in the allotted time + # + # On some runtime platforms (most notably the JVM) the application will not + # exit until all thread pools have been shutdown. To prevent applications from + # "hanging" on exit, all threads can be marked as daemon according to the + # `:auto_terminate` option. + # + # ```ruby + # pool1 = Concurrent::FixedThreadPool.new(5) # threads will be marked as daemon + # pool2 = Concurrent::FixedThreadPool.new(5, auto_terminate: false) # mark threads as non-daemon + # ``` + # + # @note Failure to properly shutdown a thread pool can lead to unpredictable results. + # Please read *Shutting Down Thread Pools* for more information. + # + # @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html Java Tutorials: Thread Pools + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html Java Executors class + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html Java ExecutorService interface + # @see https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#setDaemon-boolean- + + + + + + # @!macro fixed_thread_pool + # + # A thread pool that reuses a fixed number of threads operating off an unbounded queue. + # At any point, at most `num_threads` will be active processing tasks. When all threads are busy new + # tasks `#post` to the thread pool are enqueued until a thread becomes available. + # Should a thread crash for any reason the thread will immediately be removed + # from the pool and replaced. + # + # The API and behavior of this class are based on Java's `FixedThreadPool` + # + # @!macro thread_pool_options + class FixedThreadPool < ThreadPoolExecutor + + # @!macro fixed_thread_pool_method_initialize + # + # Create a new thread pool. + # + # @param [Integer] num_threads the number of threads to allocate + # @param [Hash] opts the options defining pool behavior. + # @option opts [Symbol] :fallback_policy (`:abort`) the fallback policy + # + # @raise [ArgumentError] if `num_threads` is less than or equal to zero + # @raise [ArgumentError] if `fallback_policy` is not a known policy + # + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int- + def initialize(num_threads, opts = {}) + raise ArgumentError.new('number of threads must be greater than zero') if num_threads.to_i < 1 + defaults = { max_queue: DEFAULT_MAX_QUEUE_SIZE, + idletime: DEFAULT_THREAD_IDLETIMEOUT } + overrides = { min_threads: num_threads, + max_threads: num_threads } + super(defaults.merge(opts).merge(overrides)) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb new file mode 100644 index 0000000000000..282df7a0593ec --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb @@ -0,0 +1,66 @@ +require 'concurrent/atomic/event' +require 'concurrent/executor/abstract_executor_service' +require 'concurrent/executor/serial_executor_service' + +module Concurrent + + # An executor service which runs all operations on the current thread, + # blocking as necessary. Operations are performed in the order they are + # received and no two operations can be performed simultaneously. + # + # This executor service exists mainly for testing an debugging. When used + # it immediately runs every `#post` operation on the current thread, blocking + # that thread until the operation is complete. This can be very beneficial + # during testing because it makes all operations deterministic. + # + # @note Intended for use primarily in testing and debugging. + class ImmediateExecutor < AbstractExecutorService + include SerialExecutorService + + # Creates a new executor + def initialize + @stopped = Concurrent::Event.new + end + + # @!macro executor_service_method_post + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + return false unless running? + task.call(*args) + true + end + + # @!macro executor_service_method_left_shift + def <<(task) + post(&task) + self + end + + # @!macro executor_service_method_running_question + def running? + ! shutdown? + end + + # @!macro executor_service_method_shuttingdown_question + def shuttingdown? + false + end + + # @!macro executor_service_method_shutdown_question + def shutdown? + @stopped.set? + end + + # @!macro executor_service_method_shutdown + def shutdown + @stopped.set + true + end + alias_method :kill, :shutdown + + # @!macro executor_service_method_wait_for_termination + def wait_for_termination(timeout = nil) + @stopped.wait(timeout) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb new file mode 100644 index 0000000000000..4f9769fa3f3b5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb @@ -0,0 +1,44 @@ +require 'concurrent/executor/immediate_executor' +require 'concurrent/executor/simple_executor_service' + +module Concurrent + # An executor service which runs all operations on a new thread, blocking + # until it completes. Operations are performed in the order they are received + # and no two operations can be performed simultaneously. + # + # This executor service exists mainly for testing an debugging. When used it + # immediately runs every `#post` operation on a new thread, blocking the + # current thread until the operation is complete. This is similar to how the + # ImmediateExecutor works, but the operation has the full stack of the new + # thread at its disposal. This can be helpful when the operations will spawn + # more operations on the same executor and so on - such a situation might + # overflow the single stack in case of an ImmediateExecutor, which is + # inconsistent with how it would behave for a threaded executor. + # + # @note Intended for use primarily in testing and debugging. + class IndirectImmediateExecutor < ImmediateExecutor + # Creates a new executor + def initialize + super + @internal_executor = SimpleExecutorService.new + end + + # @!macro executor_service_method_post + def post(*args, &task) + raise ArgumentError.new("no block given") unless block_given? + return false unless running? + + event = Concurrent::Event.new + @internal_executor.post do + begin + task.call(*args) + ensure + event.set + end + end + event.wait + + true + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb new file mode 100644 index 0000000000000..b2bc69a6ea58d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb @@ -0,0 +1,100 @@ +require 'concurrent/utility/engine' + +if Concurrent.on_jruby? + require 'concurrent/errors' + require 'concurrent/executor/abstract_executor_service' + + module Concurrent + + # @!macro abstract_executor_service_public_api + # @!visibility private + class JavaExecutorService < AbstractExecutorService + java_import 'java.lang.Runnable' + + FALLBACK_POLICY_CLASSES = { + abort: java.util.concurrent.ThreadPoolExecutor::AbortPolicy, + discard: java.util.concurrent.ThreadPoolExecutor::DiscardPolicy, + caller_runs: java.util.concurrent.ThreadPoolExecutor::CallerRunsPolicy + }.freeze + private_constant :FALLBACK_POLICY_CLASSES + + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + return fallback_action(*args, &task).call unless running? + @executor.submit Job.new(args, task) + true + rescue Java::JavaUtilConcurrent::RejectedExecutionException + raise RejectedExecutionError + end + + def wait_for_termination(timeout = nil) + if timeout.nil? + ok = @executor.awaitTermination(60, java.util.concurrent.TimeUnit::SECONDS) until ok + true + else + @executor.awaitTermination(1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS) + end + end + + def shutdown + synchronize do + @executor.shutdown + nil + end + end + + def kill + synchronize do + @executor.shutdownNow + nil + end + end + + private + + def ns_running? + !(ns_shuttingdown? || ns_shutdown?) + end + + def ns_shuttingdown? + @executor.isShutdown && !@executor.isTerminated + end + + def ns_shutdown? + @executor.isTerminated + end + + class Job + include Runnable + def initialize(args, block) + @args = args + @block = block + end + + def run + @block.call(*@args) + end + end + private_constant :Job + end + + class DaemonThreadFactory + # hide include from YARD + send :include, java.util.concurrent.ThreadFactory + + def initialize(daemonize = true) + @daemonize = daemonize + @java_thread_factory = java.util.concurrent.Executors.defaultThreadFactory + end + + def newThread(runnable) + thread = @java_thread_factory.newThread(runnable) + thread.setDaemon(@daemonize) + return thread + end + end + + private_constant :DaemonThreadFactory + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb new file mode 100644 index 0000000000000..7aa24f2d723bf --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb @@ -0,0 +1,30 @@ +if Concurrent.on_jruby? + + require 'concurrent/executor/java_executor_service' + require 'concurrent/executor/serial_executor_service' + + module Concurrent + + # @!macro single_thread_executor + # @!macro abstract_executor_service_public_api + # @!visibility private + class JavaSingleThreadExecutor < JavaExecutorService + include SerialExecutorService + + # @!macro single_thread_executor_method_initialize + def initialize(opts = {}) + super(opts) + end + + private + + def ns_initialize(opts) + @executor = java.util.concurrent.Executors.newSingleThreadExecutor( + DaemonThreadFactory.new(ns_auto_terminate?) + ) + @fallback_policy = opts.fetch(:fallback_policy, :discard) + raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.keys.include?(@fallback_policy) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb new file mode 100644 index 0000000000000..598a5f91f8822 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb @@ -0,0 +1,145 @@ +if Concurrent.on_jruby? + + require 'concurrent/executor/java_executor_service' + + module Concurrent + + # @!macro thread_pool_executor + # @!macro thread_pool_options + # @!visibility private + class JavaThreadPoolExecutor < JavaExecutorService + + # @!macro thread_pool_executor_constant_default_max_pool_size + DEFAULT_MAX_POOL_SIZE = java.lang.Integer::MAX_VALUE # 2147483647 + + # @!macro thread_pool_executor_constant_default_min_pool_size + DEFAULT_MIN_POOL_SIZE = 0 + + # @!macro thread_pool_executor_constant_default_max_queue_size + DEFAULT_MAX_QUEUE_SIZE = 0 + + # @!macro thread_pool_executor_constant_default_thread_timeout + DEFAULT_THREAD_IDLETIMEOUT = 60 + + # @!macro thread_pool_executor_constant_default_synchronous + DEFAULT_SYNCHRONOUS = false + + # @!macro thread_pool_executor_attr_reader_max_length + attr_reader :max_length + + # @!macro thread_pool_executor_attr_reader_max_queue + attr_reader :max_queue + + # @!macro thread_pool_executor_attr_reader_synchronous + attr_reader :synchronous + + # @!macro thread_pool_executor_method_initialize + def initialize(opts = {}) + super(opts) + end + + # @!macro executor_service_method_can_overflow_question + def can_overflow? + @max_queue != 0 + end + + # @!macro thread_pool_executor_attr_reader_min_length + def min_length + @executor.getCorePoolSize + end + + # @!macro thread_pool_executor_attr_reader_max_length + def max_length + @executor.getMaximumPoolSize + end + + # @!macro thread_pool_executor_attr_reader_length + def length + @executor.getPoolSize + end + + # @!macro thread_pool_executor_attr_reader_largest_length + def largest_length + @executor.getLargestPoolSize + end + + # @!macro thread_pool_executor_attr_reader_scheduled_task_count + def scheduled_task_count + @executor.getTaskCount + end + + # @!macro thread_pool_executor_attr_reader_completed_task_count + def completed_task_count + @executor.getCompletedTaskCount + end + + # @!macro thread_pool_executor_method_active_count + def active_count + @executor.getActiveCount + end + + # @!macro thread_pool_executor_attr_reader_idletime + def idletime + @executor.getKeepAliveTime(java.util.concurrent.TimeUnit::SECONDS) + end + + # @!macro thread_pool_executor_attr_reader_queue_length + def queue_length + @executor.getQueue.size + end + + # @!macro thread_pool_executor_attr_reader_remaining_capacity + def remaining_capacity + @max_queue == 0 ? -1 : @executor.getQueue.remainingCapacity + end + + # @!macro executor_service_method_running_question + def running? + super && !@executor.isTerminating + end + + # @!macro thread_pool_executor_method_prune_pool + def prune_pool + end + + private + + def ns_initialize(opts) + min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i + max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i + idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i + @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i + @synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS) + @fallback_policy = opts.fetch(:fallback_policy, :abort) + + raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0 + raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if max_length < DEFAULT_MIN_POOL_SIZE + raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if max_length > DEFAULT_MAX_POOL_SIZE + raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if min_length < DEFAULT_MIN_POOL_SIZE + raise ArgumentError.new("`min_threads` cannot be more than `max_threads`") if min_length > max_length + raise ArgumentError.new("#{fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICY_CLASSES.include?(@fallback_policy) + + if @max_queue == 0 + if @synchronous + queue = java.util.concurrent.SynchronousQueue.new + else + queue = java.util.concurrent.LinkedBlockingQueue.new + end + else + queue = java.util.concurrent.LinkedBlockingQueue.new(@max_queue) + end + + @executor = java.util.concurrent.ThreadPoolExecutor.new( + min_length, + max_length, + idletime, + java.util.concurrent.TimeUnit::SECONDS, + queue, + DaemonThreadFactory.new(ns_auto_terminate?), + FALLBACK_POLICY_CLASSES[@fallback_policy].new) + + end + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb new file mode 100644 index 0000000000000..1f7301b947434 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb @@ -0,0 +1,82 @@ +require 'concurrent/executor/abstract_executor_service' +require 'concurrent/atomic/event' + +module Concurrent + + # @!macro abstract_executor_service_public_api + # @!visibility private + class RubyExecutorService < AbstractExecutorService + safe_initialization! + + def initialize(*args, &block) + super + @StopEvent = Event.new + @StoppedEvent = Event.new + end + + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + deferred_action = synchronize { + if running? + ns_execute(*args, &task) + else + fallback_action(*args, &task) + end + } + if deferred_action + deferred_action.call + else + true + end + end + + def shutdown + synchronize do + break unless running? + stop_event.set + ns_shutdown_execution + end + true + end + + def kill + synchronize do + break if shutdown? + stop_event.set + ns_kill_execution + stopped_event.set + end + true + end + + def wait_for_termination(timeout = nil) + stopped_event.wait(timeout) + end + + private + + def stop_event + @StopEvent + end + + def stopped_event + @StoppedEvent + end + + def ns_shutdown_execution + stopped_event.set + end + + def ns_running? + !stop_event.set? + end + + def ns_shuttingdown? + !(ns_running? || ns_shutdown?) + end + + def ns_shutdown? + stopped_event.set? + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb new file mode 100644 index 0000000000000..916337d4baad1 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb @@ -0,0 +1,21 @@ +require 'concurrent/executor/ruby_thread_pool_executor' + +module Concurrent + + # @!macro single_thread_executor + # @!macro abstract_executor_service_public_api + # @!visibility private + class RubySingleThreadExecutor < RubyThreadPoolExecutor + + # @!macro single_thread_executor_method_initialize + def initialize(opts = {}) + super( + min_threads: 1, + max_threads: 1, + max_queue: 0, + idletime: DEFAULT_THREAD_IDLETIMEOUT, + fallback_policy: opts.fetch(:fallback_policy, :discard), + ) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb new file mode 100644 index 0000000000000..9375acf38402b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb @@ -0,0 +1,373 @@ +require 'thread' +require 'concurrent/atomic/event' +require 'concurrent/concern/logging' +require 'concurrent/executor/ruby_executor_service' +require 'concurrent/utility/monotonic_time' + +module Concurrent + + # @!macro thread_pool_executor + # @!macro thread_pool_options + # @!visibility private + class RubyThreadPoolExecutor < RubyExecutorService + + # @!macro thread_pool_executor_constant_default_max_pool_size + DEFAULT_MAX_POOL_SIZE = 2_147_483_647 # java.lang.Integer::MAX_VALUE + + # @!macro thread_pool_executor_constant_default_min_pool_size + DEFAULT_MIN_POOL_SIZE = 0 + + # @!macro thread_pool_executor_constant_default_max_queue_size + DEFAULT_MAX_QUEUE_SIZE = 0 + + # @!macro thread_pool_executor_constant_default_thread_timeout + DEFAULT_THREAD_IDLETIMEOUT = 60 + + # @!macro thread_pool_executor_constant_default_synchronous + DEFAULT_SYNCHRONOUS = false + + # @!macro thread_pool_executor_attr_reader_max_length + attr_reader :max_length + + # @!macro thread_pool_executor_attr_reader_min_length + attr_reader :min_length + + # @!macro thread_pool_executor_attr_reader_idletime + attr_reader :idletime + + # @!macro thread_pool_executor_attr_reader_max_queue + attr_reader :max_queue + + # @!macro thread_pool_executor_attr_reader_synchronous + attr_reader :synchronous + + # @!macro thread_pool_executor_method_initialize + def initialize(opts = {}) + super(opts) + end + + # @!macro thread_pool_executor_attr_reader_largest_length + def largest_length + synchronize { @largest_length } + end + + # @!macro thread_pool_executor_attr_reader_scheduled_task_count + def scheduled_task_count + synchronize { @scheduled_task_count } + end + + # @!macro thread_pool_executor_attr_reader_completed_task_count + def completed_task_count + synchronize { @completed_task_count } + end + + # @!macro thread_pool_executor_method_active_count + def active_count + synchronize do + @pool.length - @ready.length + end + end + + # @!macro executor_service_method_can_overflow_question + def can_overflow? + synchronize { ns_limited_queue? } + end + + # @!macro thread_pool_executor_attr_reader_length + def length + synchronize { @pool.length } + end + + # @!macro thread_pool_executor_attr_reader_queue_length + def queue_length + synchronize { @queue.length } + end + + # @!macro thread_pool_executor_attr_reader_remaining_capacity + def remaining_capacity + synchronize do + if ns_limited_queue? + @max_queue - @queue.length + else + -1 + end + end + end + + # @!visibility private + def remove_busy_worker(worker) + synchronize { ns_remove_busy_worker worker } + end + + # @!visibility private + def ready_worker(worker, last_message) + synchronize { ns_ready_worker worker, last_message } + end + + # @!visibility private + def worker_died(worker) + synchronize { ns_worker_died worker } + end + + # @!visibility private + def worker_task_completed + synchronize { @completed_task_count += 1 } + end + + # @!macro thread_pool_executor_method_prune_pool + def prune_pool + synchronize { ns_prune_pool } + end + + private + + # @!visibility private + def ns_initialize(opts) + @min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i + @max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i + @idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i + @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i + @synchronous = opts.fetch(:synchronous, DEFAULT_SYNCHRONOUS) + @fallback_policy = opts.fetch(:fallback_policy, :abort) + + raise ArgumentError.new("`synchronous` cannot be set unless `max_queue` is 0") if @synchronous && @max_queue > 0 + raise ArgumentError.new("#{@fallback_policy} is not a valid fallback policy") unless FALLBACK_POLICIES.include?(@fallback_policy) + raise ArgumentError.new("`max_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @max_length < DEFAULT_MIN_POOL_SIZE + raise ArgumentError.new("`max_threads` cannot be greater than #{DEFAULT_MAX_POOL_SIZE}") if @max_length > DEFAULT_MAX_POOL_SIZE + raise ArgumentError.new("`min_threads` cannot be less than #{DEFAULT_MIN_POOL_SIZE}") if @min_length < DEFAULT_MIN_POOL_SIZE + raise ArgumentError.new("`min_threads` cannot be more than `max_threads`") if min_length > max_length + + @pool = [] # all workers + @ready = [] # used as a stash (most idle worker is at the start) + @queue = [] # used as queue + # @ready or @queue is empty at all times + @scheduled_task_count = 0 + @completed_task_count = 0 + @largest_length = 0 + @workers_counter = 0 + @ruby_pid = $$ # detects if Ruby has forked + + @gc_interval = opts.fetch(:gc_interval, @idletime / 2.0).to_i # undocumented + @next_gc_time = Concurrent.monotonic_time + @gc_interval + end + + # @!visibility private + def ns_limited_queue? + @max_queue != 0 + end + + # @!visibility private + def ns_execute(*args, &task) + ns_reset_if_forked + + if ns_assign_worker(*args, &task) || ns_enqueue(*args, &task) + @scheduled_task_count += 1 + else + return fallback_action(*args, &task) + end + + ns_prune_pool if @next_gc_time < Concurrent.monotonic_time + nil + end + + # @!visibility private + def ns_shutdown_execution + ns_reset_if_forked + + if @pool.empty? + # nothing to do + stopped_event.set + end + + if @queue.empty? + # no more tasks will be accepted, just stop all workers + @pool.each(&:stop) + end + end + + # @!visibility private + def ns_kill_execution + # TODO log out unprocessed tasks in queue + # TODO try to shutdown first? + @pool.each(&:kill) + @pool.clear + @ready.clear + end + + # tries to assign task to a worker, tries to get one from @ready or to create new one + # @return [true, false] if task is assigned to a worker + # + # @!visibility private + def ns_assign_worker(*args, &task) + # keep growing if the pool is not at the minimum yet + worker, _ = (@ready.pop if @pool.size >= @min_length) || ns_add_busy_worker + if worker + worker << [task, args] + true + else + false + end + rescue ThreadError + # Raised when the operating system refuses to create the new thread + return false + end + + # tries to enqueue task + # @return [true, false] if enqueued + # + # @!visibility private + def ns_enqueue(*args, &task) + return false if @synchronous + + if !ns_limited_queue? || @queue.size < @max_queue + @queue << [task, args] + true + else + false + end + end + + # @!visibility private + def ns_worker_died(worker) + ns_remove_busy_worker worker + replacement_worker = ns_add_busy_worker + ns_ready_worker replacement_worker, Concurrent.monotonic_time, false if replacement_worker + end + + # creates new worker which has to receive work to do after it's added + # @return [nil, Worker] nil of max capacity is reached + # + # @!visibility private + def ns_add_busy_worker + return if @pool.size >= @max_length + + @workers_counter += 1 + @pool << (worker = Worker.new(self, @workers_counter)) + @largest_length = @pool.length if @pool.length > @largest_length + worker + end + + # handle ready worker, giving it new job or assigning back to @ready + # + # @!visibility private + def ns_ready_worker(worker, last_message, success = true) + task_and_args = @queue.shift + if task_and_args + worker << task_and_args + else + # stop workers when !running?, do not return them to @ready + if running? + raise unless last_message + @ready.push([worker, last_message]) + else + worker.stop + end + end + end + + # removes a worker which is not in not tracked in @ready + # + # @!visibility private + def ns_remove_busy_worker(worker) + @pool.delete(worker) + stopped_event.set if @pool.empty? && !running? + true + end + + # try oldest worker if it is idle for enough time, it's returned back at the start + # + # @!visibility private + def ns_prune_pool + now = Concurrent.monotonic_time + stopped_workers = 0 + while !@ready.empty? && (@pool.size - stopped_workers > @min_length) + worker, last_message = @ready.first + if now - last_message > self.idletime + stopped_workers += 1 + @ready.shift + worker << :stop + else break + end + end + + @next_gc_time = Concurrent.monotonic_time + @gc_interval + end + + def ns_reset_if_forked + if $$ != @ruby_pid + @queue.clear + @ready.clear + @pool.clear + @scheduled_task_count = 0 + @completed_task_count = 0 + @largest_length = 0 + @workers_counter = 0 + @ruby_pid = $$ + end + end + + # @!visibility private + class Worker + include Concern::Logging + + def initialize(pool, id) + # instance variables accessed only under pool's lock so no need to sync here again + @queue = Queue.new + @pool = pool + @thread = create_worker @queue, pool, pool.idletime + + if @thread.respond_to?(:name=) + @thread.name = [pool.name, 'worker', id].compact.join('-') + end + end + + def <<(message) + @queue << message + end + + def stop + @queue << :stop + end + + def kill + @thread.kill + end + + private + + def create_worker(queue, pool, idletime) + Thread.new(queue, pool, idletime) do |my_queue, my_pool, my_idletime| + catch(:stop) do + loop do + + case message = my_queue.pop + when :stop + my_pool.remove_busy_worker(self) + throw :stop + + else + task, args = message + run_task my_pool, task, args + my_pool.ready_worker(self, Concurrent.monotonic_time) + end + end + end + end + end + + def run_task(pool, task, args) + task.call(*args) + pool.worker_task_completed + rescue => ex + # let it fail + log DEBUG, ex + rescue Exception => ex + log ERROR, ex + pool.worker_died(self) + throw :stop + end + end + + private_constant :Worker + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb new file mode 100644 index 0000000000000..f796b8571fa44 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb @@ -0,0 +1,35 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # A simple utility class that executes a callable and returns and array of three elements: + # success - indicating if the callable has been executed without errors + # value - filled by the callable result if it has been executed without errors, nil otherwise + # reason - the error risen by the callable if it has been executed with errors, nil otherwise + class SafeTaskExecutor < Synchronization::LockableObject + + def initialize(task, opts = {}) + @task = task + @exception_class = opts.fetch(:rescue_exception, false) ? Exception : StandardError + super() # ensures visibility + end + + # @return [Array] + def execute(*args) + success = true + value = reason = nil + + synchronize do + begin + value = @task.call(*args) + success = true + rescue @exception_class => ex + reason = ex + success = false + end + end + + [success, value, reason] + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb new file mode 100644 index 0000000000000..f1c38ecfa9c97 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb @@ -0,0 +1,34 @@ +require 'concurrent/executor/executor_service' + +module Concurrent + + # Indicates that the including `ExecutorService` guarantees + # that all operations will occur in the order they are post and that no + # two operations may occur simultaneously. This module provides no + # functionality and provides no guarantees. That is the responsibility + # of the including class. This module exists solely to allow the including + # object to be interrogated for its serialization status. + # + # @example + # class Foo + # include Concurrent::SerialExecutor + # end + # + # foo = Foo.new + # + # foo.is_a? Concurrent::ExecutorService #=> true + # foo.is_a? Concurrent::SerialExecutor #=> true + # foo.serialized? #=> true + # + # @!visibility private + module SerialExecutorService + include ExecutorService + + # @!macro executor_service_method_serialized_question + # + # @note Always returns `true` + def serialized? + true + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb new file mode 100644 index 0000000000000..4db7c7f0c2135 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb @@ -0,0 +1,107 @@ +require 'concurrent/errors' +require 'concurrent/concern/logging' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # Ensures passed jobs in a serialized order never running at the same time. + class SerializedExecution < Synchronization::LockableObject + include Concern::Logging + + def initialize() + super() + synchronize { ns_initialize } + end + + Job = Struct.new(:executor, :args, :block) do + def call + block.call(*args) + end + end + + # Submit a task to the executor for asynchronous processing. + # + # @param [Executor] executor to be used for this job + # + # @param [Array] args zero or more arguments to be passed to the task + # + # @yield the asynchronous task to perform + # + # @return [Boolean] `true` if the task is queued, `false` if the executor + # is not running + # + # @raise [ArgumentError] if no task is given + def post(executor, *args, &task) + posts [[executor, args, task]] + true + end + + # As {#post} but allows to submit multiple tasks at once, it's guaranteed that they will not + # be interleaved by other tasks. + # + # @param [Array, Proc)>] posts array of triplets where + # first is a {ExecutorService}, second is array of args for task, third is a task (Proc) + def posts(posts) + # if can_overflow? + # raise ArgumentError, 'SerializedExecution does not support thread-pools which can overflow' + # end + + return nil if posts.empty? + + jobs = posts.map { |executor, args, task| Job.new executor, args, task } + + job_to_post = synchronize do + if @being_executed + @stash.push(*jobs) + nil + else + @being_executed = true + @stash.push(*jobs[1..-1]) + jobs.first + end + end + + call_job job_to_post if job_to_post + true + end + + private + + def ns_initialize + @being_executed = false + @stash = [] + end + + def call_job(job) + did_it_run = begin + job.executor.post { work(job) } + true + rescue RejectedExecutionError => ex + false + end + + # TODO not the best idea to run it myself + unless did_it_run + begin + work job + rescue => ex + # let it fail + log DEBUG, ex + end + end + end + + # ensures next job is executed if any is stashed + def work(job) + job.call + ensure + synchronize do + job = @stash.shift || (@being_executed = false) + end + + # TODO maybe be able to tell caching pool to just enqueue this job, because the current one end at the end + # of this block + call_job job if job + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb new file mode 100644 index 0000000000000..8197781b52f4e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb @@ -0,0 +1,28 @@ +require 'delegate' +require 'concurrent/executor/serial_executor_service' +require 'concurrent/executor/serialized_execution' + +module Concurrent + + # A wrapper/delegator for any `ExecutorService` that + # guarantees serialized execution of tasks. + # + # @see [SimpleDelegator](http://www.ruby-doc.org/stdlib-2.1.2/libdoc/delegate/rdoc/SimpleDelegator.html) + # @see Concurrent::SerializedExecution + class SerializedExecutionDelegator < SimpleDelegator + include SerialExecutorService + + def initialize(executor) + @executor = executor + @serializer = SerializedExecution.new + super(executor) + end + + # @!macro executor_service_method_post + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + return false unless running? + @serializer.post(@executor, *args, &task) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb new file mode 100644 index 0000000000000..0bc62afd38d20 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb @@ -0,0 +1,103 @@ +require 'concurrent/atomic/atomic_boolean' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/atomic/event' +require 'concurrent/executor/executor_service' +require 'concurrent/executor/ruby_executor_service' + +module Concurrent + + # An executor service in which every operation spawns a new, + # independently operating thread. + # + # This is perhaps the most inefficient executor service in this + # library. It exists mainly for testing an debugging. Thread creation + # and management is expensive in Ruby and this executor performs no + # resource pooling. This can be very beneficial during testing and + # debugging because it decouples the using code from the underlying + # executor implementation. In production this executor will likely + # lead to suboptimal performance. + # + # @note Intended for use primarily in testing and debugging. + class SimpleExecutorService < RubyExecutorService + + # @!macro executor_service_method_post + def self.post(*args) + raise ArgumentError.new('no block given') unless block_given? + Thread.new(*args) do + Thread.current.abort_on_exception = false + yield(*args) + end + true + end + + # @!macro executor_service_method_left_shift + def self.<<(task) + post(&task) + self + end + + # @!macro executor_service_method_post + def post(*args, &task) + raise ArgumentError.new('no block given') unless block_given? + return false unless running? + @count.increment + Thread.new(*args) do + Thread.current.abort_on_exception = false + begin + yield(*args) + ensure + @count.decrement + @stopped.set if @running.false? && @count.value == 0 + end + end + end + + # @!macro executor_service_method_left_shift + def <<(task) + post(&task) + self + end + + # @!macro executor_service_method_running_question + def running? + @running.true? + end + + # @!macro executor_service_method_shuttingdown_question + def shuttingdown? + @running.false? && ! @stopped.set? + end + + # @!macro executor_service_method_shutdown_question + def shutdown? + @stopped.set? + end + + # @!macro executor_service_method_shutdown + def shutdown + @running.make_false + @stopped.set if @count.value == 0 + true + end + + # @!macro executor_service_method_kill + def kill + @running.make_false + @stopped.set + true + end + + # @!macro executor_service_method_wait_for_termination + def wait_for_termination(timeout = nil) + @stopped.wait(timeout) + end + + private + + def ns_initialize(*args) + @running = Concurrent::AtomicBoolean.new(true) + @stopped = Concurrent::Event.new + @count = Concurrent::AtomicFixnum.new(0) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb new file mode 100644 index 0000000000000..f1474ea9ff46f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb @@ -0,0 +1,57 @@ +require 'concurrent/utility/engine' +require 'concurrent/executor/ruby_single_thread_executor' + +module Concurrent + + if Concurrent.on_jruby? + require 'concurrent/executor/java_single_thread_executor' + end + + SingleThreadExecutorImplementation = case + when Concurrent.on_jruby? + JavaSingleThreadExecutor + else + RubySingleThreadExecutor + end + private_constant :SingleThreadExecutorImplementation + + # @!macro single_thread_executor + # + # A thread pool with a single thread an unlimited queue. Should the thread + # die for any reason it will be removed and replaced, thus ensuring that + # the executor will always remain viable and available to process jobs. + # + # A common pattern for background processing is to create a single thread + # on which an infinite loop is run. The thread's loop blocks on an input + # source (perhaps blocking I/O or a queue) and processes each input as it + # is received. This pattern has several issues. The thread itself is highly + # susceptible to errors during processing. Also, the thread itself must be + # constantly monitored and restarted should it die. `SingleThreadExecutor` + # encapsulates all these bahaviors. The task processor is highly resilient + # to errors from within tasks. Also, should the thread die it will + # automatically be restarted. + # + # The API and behavior of this class are based on Java's `SingleThreadExecutor`. + # + # @!macro abstract_executor_service_public_api + class SingleThreadExecutor < SingleThreadExecutorImplementation + + # @!macro single_thread_executor_method_initialize + # + # Create a new thread pool. + # + # @option opts [Symbol] :fallback_policy (:discard) the policy for handling new + # tasks that are received when the queue size has reached + # `max_queue` or the executor has shut down + # + # @raise [ArgumentError] if `:fallback_policy` is not one of the values specified + # in `FALLBACK_POLICIES` + # + # @see http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html + # @see http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html + + # @!method initialize(opts = {}) + # @!macro single_thread_executor_method_initialize + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb new file mode 100644 index 0000000000000..253d46a9d1d0d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb @@ -0,0 +1,88 @@ +require 'concurrent/utility/engine' +require 'concurrent/executor/ruby_thread_pool_executor' + +module Concurrent + + if Concurrent.on_jruby? + require 'concurrent/executor/java_thread_pool_executor' + end + + ThreadPoolExecutorImplementation = case + when Concurrent.on_jruby? + JavaThreadPoolExecutor + else + RubyThreadPoolExecutor + end + private_constant :ThreadPoolExecutorImplementation + + # @!macro thread_pool_executor + # + # An abstraction composed of one or more threads and a task queue. Tasks + # (blocks or `proc` objects) are submitted to the pool and added to the queue. + # The threads in the pool remove the tasks and execute them in the order + # they were received. + # + # A `ThreadPoolExecutor` will automatically adjust the pool size according + # to the bounds set by `min-threads` and `max-threads`. When a new task is + # submitted and fewer than `min-threads` threads are running, a new thread + # is created to handle the request, even if other worker threads are idle. + # If there are more than `min-threads` but less than `max-threads` threads + # running, a new thread will be created only if the queue is full. + # + # Threads that are idle for too long will be garbage collected, down to the + # configured minimum options. Should a thread crash it, too, will be garbage collected. + # + # `ThreadPoolExecutor` is based on the Java class of the same name. From + # the official Java documentation; + # + # > Thread pools address two different problems: they usually provide + # > improved performance when executing large numbers of asynchronous tasks, + # > due to reduced per-task invocation overhead, and they provide a means + # > of bounding and managing the resources, including threads, consumed + # > when executing a collection of tasks. Each ThreadPoolExecutor also + # > maintains some basic statistics, such as the number of completed tasks. + # > + # > To be useful across a wide range of contexts, this class provides many + # > adjustable parameters and extensibility hooks. However, programmers are + # > urged to use the more convenient Executors factory methods + # > [CachedThreadPool] (unbounded thread pool, with automatic thread reclamation), + # > [FixedThreadPool] (fixed size thread pool) and [SingleThreadExecutor] (single + # > background thread), that preconfigure settings for the most common usage + # > scenarios. + # + # @!macro thread_pool_options + # + # @!macro thread_pool_executor_public_api + class ThreadPoolExecutor < ThreadPoolExecutorImplementation + + # @!macro thread_pool_executor_method_initialize + # + # Create a new thread pool. + # + # @param [Hash] opts the options which configure the thread pool. + # + # @option opts [Integer] :max_threads (DEFAULT_MAX_POOL_SIZE) the maximum + # number of threads to be created + # @option opts [Integer] :min_threads (DEFAULT_MIN_POOL_SIZE) When a new task is submitted + # and fewer than `min_threads` are running, a new thread is created + # @option opts [Integer] :idletime (DEFAULT_THREAD_IDLETIMEOUT) the maximum + # number of seconds a thread may be idle before being reclaimed + # @option opts [Integer] :max_queue (DEFAULT_MAX_QUEUE_SIZE) the maximum + # number of tasks allowed in the work queue at any one time; a value of + # zero means the queue may grow without bound + # @option opts [Symbol] :fallback_policy (:abort) the policy for handling new + # tasks that are received when the queue size has reached + # `max_queue` or the executor has shut down + # @option opts [Boolean] :synchronous (DEFAULT_SYNCHRONOUS) whether or not a value of 0 + # for :max_queue means the queue must perform direct hand-off rather than unbounded. + # @raise [ArgumentError] if `:max_threads` is less than one + # @raise [ArgumentError] if `:min_threads` is less than zero + # @raise [ArgumentError] if `:fallback_policy` is not one of the values specified + # in `FALLBACK_POLICIES` + # + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html + + # @!method initialize(opts = {}) + # @!macro thread_pool_executor_method_initialize + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/timer_set.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/timer_set.rb new file mode 100644 index 0000000000000..759dce093a5b6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executor/timer_set.rb @@ -0,0 +1,176 @@ +require 'concurrent/scheduled_task' +require 'concurrent/atomic/event' +require 'concurrent/collection/non_concurrent_priority_queue' +require 'concurrent/executor/executor_service' +require 'concurrent/executor/single_thread_executor' +require 'concurrent/errors' +require 'concurrent/options' + +module Concurrent + + # Executes a collection of tasks, each after a given delay. A master task + # monitors the set and schedules each task for execution at the appropriate + # time. Tasks are run on the global thread pool or on the supplied executor. + # Each task is represented as a `ScheduledTask`. + # + # @see Concurrent::ScheduledTask + # + # @!macro monotonic_clock_warning + class TimerSet < RubyExecutorService + + # Create a new set of timed tasks. + # + # @!macro executor_options + # + # @param [Hash] opts the options used to specify the executor on which to perform actions + # @option opts [Executor] :executor when set use the given `Executor` instance. + # Three special values are also supported: `:task` returns the global task pool, + # `:operation` returns the global operation pool, and `:immediate` returns a new + # `ImmediateExecutor` object. + def initialize(opts = {}) + super(opts) + end + + # Post a task to be execute run after a given delay (in seconds). If the + # delay is less than 1/100th of a second the task will be immediately post + # to the executor. + # + # @param [Float] delay the number of seconds to wait for before executing the task. + # @param [Array] args the arguments passed to the task on execution. + # + # @yield the task to be performed. + # + # @return [Concurrent::ScheduledTask, false] IVar representing the task if the post + # is successful; false after shutdown. + # + # @raise [ArgumentError] if the intended execution time is not in the future. + # @raise [ArgumentError] if no block is given. + def post(delay, *args, &task) + raise ArgumentError.new('no block given') unless block_given? + return false unless running? + opts = { executor: @task_executor, + args: args, + timer_set: self } + task = ScheduledTask.execute(delay, opts, &task) # may raise exception + task.unscheduled? ? false : task + end + + # Begin an immediate shutdown. In-progress tasks will be allowed to + # complete but enqueued tasks will be dismissed and no new tasks + # will be accepted. Has no additional effect if the thread pool is + # not running. + def kill + shutdown + end + + private :<< + + private + + # Initialize the object. + # + # @param [Hash] opts the options to create the object with. + # @!visibility private + def ns_initialize(opts) + @queue = Collection::NonConcurrentPriorityQueue.new(order: :min) + @task_executor = Options.executor_from_options(opts) || Concurrent.global_io_executor + @timer_executor = SingleThreadExecutor.new + @condition = Event.new + @ruby_pid = $$ # detects if Ruby has forked + end + + # Post the task to the internal queue. + # + # @note This is intended as a callback method from ScheduledTask + # only. It is not intended to be used directly. Post a task + # by using the `SchedulesTask#execute` method. + # + # @!visibility private + def post_task(task) + synchronize { ns_post_task(task) } + end + + # @!visibility private + def ns_post_task(task) + return false unless ns_running? + ns_reset_if_forked + if (task.initial_delay) <= 0.01 + task.executor.post { task.process_task } + else + @queue.push(task) + # only post the process method when the queue is empty + @timer_executor.post(&method(:process_tasks)) if @queue.length == 1 + @condition.set + end + true + end + + # Remove the given task from the queue. + # + # @note This is intended as a callback method from `ScheduledTask` + # only. It is not intended to be used directly. Cancel a task + # by using the `ScheduledTask#cancel` method. + # + # @!visibility private + def remove_task(task) + synchronize { @queue.delete(task) } + end + + # `ExecutorService` callback called during shutdown. + # + # @!visibility private + def ns_shutdown_execution + ns_reset_if_forked + @queue.clear + @timer_executor.kill + stopped_event.set + end + + def ns_reset_if_forked + if $$ != @ruby_pid + @queue.clear + @condition.reset + @ruby_pid = $$ + end + end + + # Run a loop and execute tasks in the scheduled order and at the approximate + # scheduled time. If no tasks remain the thread will exit gracefully so that + # garbage collection can occur. If there are no ready tasks it will sleep + # for up to 60 seconds waiting for the next scheduled task. + # + # @!visibility private + def process_tasks + loop do + task = synchronize { @condition.reset; @queue.peek } + break unless task + + now = Concurrent.monotonic_time + diff = task.schedule_time - now + + if diff <= 0 + # We need to remove the task from the queue before passing + # it to the executor, to avoid race conditions where we pass + # the peek'ed task to the executor and then pop a different + # one that's been added in the meantime. + # + # Note that there's no race condition between the peek and + # this pop - this pop could retrieve a different task from + # the peek, but that task would be due to fire now anyway + # (because @queue is a priority queue, and this thread is + # the only reader, so whatever timer is at the head of the + # queue now must have the same pop time, or a closer one, as + # when we peeked). + task = synchronize { @queue.pop } + begin + task.executor.post { task.process_task } + rescue RejectedExecutionError + # ignore and continue + end + else + @condition.wait([diff, 60].min) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executors.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executors.rb new file mode 100644 index 0000000000000..eb1972ce697a9 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/executors.rb @@ -0,0 +1,20 @@ +require 'concurrent/executor/abstract_executor_service' +require 'concurrent/executor/cached_thread_pool' +require 'concurrent/executor/executor_service' +require 'concurrent/executor/fixed_thread_pool' +require 'concurrent/executor/immediate_executor' +require 'concurrent/executor/indirect_immediate_executor' +require 'concurrent/executor/java_executor_service' +require 'concurrent/executor/java_single_thread_executor' +require 'concurrent/executor/java_thread_pool_executor' +require 'concurrent/executor/ruby_executor_service' +require 'concurrent/executor/ruby_single_thread_executor' +require 'concurrent/executor/ruby_thread_pool_executor' +require 'concurrent/executor/cached_thread_pool' +require 'concurrent/executor/safe_task_executor' +require 'concurrent/executor/serial_executor_service' +require 'concurrent/executor/serialized_execution' +require 'concurrent/executor/serialized_execution_delegator' +require 'concurrent/executor/single_thread_executor' +require 'concurrent/executor/thread_pool_executor' +require 'concurrent/executor/timer_set' diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/future.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/future.rb new file mode 100644 index 0000000000000..1af182ecb2805 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/future.rb @@ -0,0 +1,141 @@ +require 'thread' +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/ivar' +require 'concurrent/executor/safe_task_executor' + +require 'concurrent/options' + +# TODO (pitr-ch 14-Mar-2017): deprecate, Future, Promise, etc. + + +module Concurrent + + # {include:file:docs-source/future.md} + # + # @!macro copy_options + # + # @see http://ruby-doc.org/stdlib-2.1.1/libdoc/observer/rdoc/Observable.html Ruby Observable module + # @see http://clojuredocs.org/clojure_core/clojure.core/future Clojure's future function + # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html java.util.concurrent.Future + class Future < IVar + + # Create a new `Future` in the `:unscheduled` state. + # + # @yield the asynchronous operation to perform + # + # @!macro executor_and_deref_options + # + # @option opts [object, Array] :args zero or more arguments to be passed the task + # block on execution + # + # @raise [ArgumentError] if no block is given + def initialize(opts = {}, &block) + raise ArgumentError.new('no block given') unless block_given? + super(NULL, opts.merge(__task_from_block__: block), &nil) + end + + # Execute an `:unscheduled` `Future`. Immediately sets the state to `:pending` and + # passes the block to a new thread/thread pool for eventual execution. + # Does nothing if the `Future` is in any state other than `:unscheduled`. + # + # @return [Future] a reference to `self` + # + # @example Instance and execute in separate steps + # future = Concurrent::Future.new{ sleep(1); 42 } + # future.state #=> :unscheduled + # future.execute + # future.state #=> :pending + # + # @example Instance and execute in one line + # future = Concurrent::Future.new{ sleep(1); 42 }.execute + # future.state #=> :pending + def execute + if compare_and_set_state(:pending, :unscheduled) + @executor.post{ safe_execute(@task, @args) } + self + end + end + + # Create a new `Future` object with the given block, execute it, and return the + # `:pending` object. + # + # @yield the asynchronous operation to perform + # + # @!macro executor_and_deref_options + # + # @option opts [object, Array] :args zero or more arguments to be passed the task + # block on execution + # + # @raise [ArgumentError] if no block is given + # + # @return [Future] the newly created `Future` in the `:pending` state + # + # @example + # future = Concurrent::Future.execute{ sleep(1); 42 } + # future.state #=> :pending + def self.execute(opts = {}, &block) + Future.new(opts, &block).execute + end + + # @!macro ivar_set_method + def set(value = NULL, &block) + check_for_block_or_value!(block_given?, value) + synchronize do + if @state != :unscheduled + raise MultipleAssignmentError + else + @task = block || Proc.new { value } + end + end + execute + end + + # Attempt to cancel the operation if it has not already processed. + # The operation can only be cancelled while still `pending`. It cannot + # be cancelled once it has begun processing or has completed. + # + # @return [Boolean] was the operation successfully cancelled. + def cancel + if compare_and_set_state(:cancelled, :pending) + complete(false, nil, CancelledOperationError.new) + true + else + false + end + end + + # Has the operation been successfully cancelled? + # + # @return [Boolean] + def cancelled? + state == :cancelled + end + + # Wait the given number of seconds for the operation to complete. + # On timeout attempt to cancel the operation. + # + # @param [Numeric] timeout the maximum time in seconds to wait. + # @return [Boolean] true if the operation completed before the timeout + # else false + def wait_or_cancel(timeout) + wait(timeout) + if complete? + true + else + cancel + false + end + end + + protected + + def ns_initialize(value, opts) + super + @state = :unscheduled + @task = opts[:__task_from_block__] + @executor = Options.executor_from_options(opts) || Concurrent.global_io_executor + @args = get_arguments_from(opts) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/hash.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/hash.rb new file mode 100644 index 0000000000000..db0208e0174fc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/hash.rb @@ -0,0 +1,52 @@ +require 'concurrent/utility/engine' +require 'concurrent/thread_safe/util' + +module Concurrent + + # @!macro concurrent_hash + # + # A thread-safe subclass of Hash. This version locks against the object + # itself for every method call, ensuring only one thread can be reading + # or writing at a time. This includes iteration methods like `#each`, + # which takes the lock repeatedly when reading an item. + # + # @see http://ruby-doc.org/core/Hash.html Ruby standard library `Hash` + + # @!macro internal_implementation_note + HashImplementation = case + when Concurrent.on_cruby? + # Hash is not fully thread-safe on CRuby, see + # https://bugs.ruby-lang.org/issues/19237 + # https://github.com/ruby/ruby/commit/ffd52412ab + # https://github.com/ruby-concurrency/concurrent-ruby/issues/929 + # So we will need to add synchronization here (similar to Concurrent::Map). + ::Hash + + when Concurrent.on_jruby? + require 'jruby/synchronized' + + class JRubyHash < ::Hash + include JRuby::Synchronized + end + JRubyHash + + when Concurrent.on_truffleruby? + require 'concurrent/thread_safe/util/data_structures' + + class TruffleRubyHash < ::Hash + end + + ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubyHash + TruffleRubyHash + + else + warn 'Possibly unsupported Ruby implementation' + ::Hash + end + private_constant :HashImplementation + + # @!macro concurrent_hash + class Hash < HashImplementation + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/immutable_struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/immutable_struct.rb new file mode 100644 index 0000000000000..48462e8375b87 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/immutable_struct.rb @@ -0,0 +1,101 @@ +require 'concurrent/synchronization/abstract_struct' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # A thread-safe, immutable variation of Ruby's standard `Struct`. + # + # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` + module ImmutableStruct + include Synchronization::AbstractStruct + + def self.included(base) + base.safe_initialization! + end + + # @!macro struct_values + def values + ns_values + end + + alias_method :to_a, :values + + # @!macro struct_values_at + def values_at(*indexes) + ns_values_at(indexes) + end + + # @!macro struct_inspect + def inspect + ns_inspect + end + + alias_method :to_s, :inspect + + # @!macro struct_merge + def merge(other, &block) + ns_merge(other, &block) + end + + # @!macro struct_to_h + def to_h + ns_to_h + end + + # @!macro struct_get + def [](member) + ns_get(member) + end + + # @!macro struct_equality + def ==(other) + ns_equality(other) + end + + # @!macro struct_each + def each(&block) + return enum_for(:each) unless block_given? + ns_each(&block) + end + + # @!macro struct_each_pair + def each_pair(&block) + return enum_for(:each_pair) unless block_given? + ns_each_pair(&block) + end + + # @!macro struct_select + def select(&block) + return enum_for(:select) unless block_given? + ns_select(&block) + end + + private + + # @!visibility private + def initialize_copy(original) + super(original) + ns_initialize_copy + end + + # @!macro struct_new + def self.new(*args, &block) + clazz_name = nil + if args.length == 0 + raise ArgumentError.new('wrong number of arguments (0 for 1+)') + elsif args.length > 0 && args.first.is_a?(String) + clazz_name = args.shift + end + FACTORY.define_struct(clazz_name, args, &block) + end + + FACTORY = Class.new(Synchronization::LockableObject) do + def define_struct(name, members, &block) + synchronize do + Synchronization::AbstractStruct.define_struct_class(ImmutableStruct, Synchronization::Object, name, members, &block) + end + end + end.new + private_constant :FACTORY + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/ivar.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/ivar.rb new file mode 100644 index 0000000000000..4165038f8945b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/ivar.rb @@ -0,0 +1,208 @@ +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/collection/copy_on_write_observer_set' +require 'concurrent/concern/obligation' +require 'concurrent/concern/observable' +require 'concurrent/executor/safe_task_executor' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # An `IVar` is like a future that you can assign. As a future is a value that + # is being computed that you can wait on, an `IVar` is a value that is waiting + # to be assigned, that you can wait on. `IVars` are single assignment and + # deterministic. + # + # Then, express futures as an asynchronous computation that assigns an `IVar`. + # The `IVar` becomes the primitive on which [futures](Future) and + # [dataflow](Dataflow) are built. + # + # An `IVar` is a single-element container that is normally created empty, and + # can only be set once. The I in `IVar` stands for immutable. Reading an + # `IVar` normally blocks until it is set. It is safe to set and read an `IVar` + # from different threads. + # + # If you want to have some parallel task set the value in an `IVar`, you want + # a `Future`. If you want to create a graph of parallel tasks all executed + # when the values they depend on are ready you want `dataflow`. `IVar` is + # generally a low-level primitive. + # + # ## Examples + # + # Create, set and get an `IVar` + # + # ```ruby + # ivar = Concurrent::IVar.new + # ivar.set 14 + # ivar.value #=> 14 + # ivar.set 2 # would now be an error + # ``` + # + # ## See Also + # + # 1. For the theory: Arvind, R. Nikhil, and K. Pingali. + # [I-Structures: Data structures for parallel computing](http://dl.acm.org/citation.cfm?id=69562). + # In Proceedings of Workshop on Graph Reduction, 1986. + # 2. For recent application: + # [DataDrivenFuture in Habanero Java from Rice](http://www.cs.rice.edu/~vs3/hjlib/doc/edu/rice/hj/api/HjDataDrivenFuture.html). + class IVar < Synchronization::LockableObject + include Concern::Obligation + include Concern::Observable + + # Create a new `IVar` in the `:pending` state with the (optional) initial value. + # + # @param [Object] value the initial value + # @param [Hash] opts the options to create a message with + # @option opts [String] :dup_on_deref (false) call `#dup` before returning + # the data + # @option opts [String] :freeze_on_deref (false) call `#freeze` before + # returning the data + # @option opts [String] :copy_on_deref (nil) call the given `Proc` passing + # the internal value and returning the value returned from the proc + def initialize(value = NULL, opts = {}, &block) + if value != NULL && block_given? + raise ArgumentError.new('provide only a value or a block') + end + super(&nil) + synchronize { ns_initialize(value, opts, &block) } + end + + # Add an observer on this object that will receive notification on update. + # + # Upon completion the `IVar` will notify all observers in a thread-safe way. + # The `func` method of the observer will be called with three arguments: the + # `Time` at which the `Future` completed the asynchronous operation, the + # final `value` (or `nil` on rejection), and the final `reason` (or `nil` on + # fulfillment). + # + # @param [Object] observer the object that will be notified of changes + # @param [Symbol] func symbol naming the method to call when this + # `Observable` has changes` + def add_observer(observer = nil, func = :update, &block) + raise ArgumentError.new('cannot provide both an observer and a block') if observer && block + direct_notification = false + + if block + observer = block + func = :call + end + + synchronize do + if event.set? + direct_notification = true + else + observers.add_observer(observer, func) + end + end + + observer.send(func, Time.now, self.value, reason) if direct_notification + observer + end + + # @!macro ivar_set_method + # Set the `IVar` to a value and wake or notify all threads waiting on it. + # + # @!macro ivar_set_parameters_and_exceptions + # @param [Object] value the value to store in the `IVar` + # @yield A block operation to use for setting the value + # @raise [ArgumentError] if both a value and a block are given + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # + # @return [IVar] self + def set(value = NULL) + check_for_block_or_value!(block_given?, value) + raise MultipleAssignmentError unless compare_and_set_state(:processing, :pending) + + begin + value = yield if block_given? + complete_without_notification(true, value, nil) + rescue => ex + complete_without_notification(false, nil, ex) + end + + notify_observers(self.value, reason) + self + end + + # @!macro ivar_fail_method + # Set the `IVar` to failed due to some error and wake or notify all threads waiting on it. + # + # @param [Object] reason for the failure + # @raise [Concurrent::MultipleAssignmentError] if the `IVar` has already + # been set or otherwise completed + # @return [IVar] self + def fail(reason = StandardError.new) + complete(false, nil, reason) + end + + # Attempt to set the `IVar` with the given value or block. Return a + # boolean indicating the success or failure of the set operation. + # + # @!macro ivar_set_parameters_and_exceptions + # + # @return [Boolean] true if the value was set else false + def try_set(value = NULL, &block) + set(value, &block) + true + rescue MultipleAssignmentError + false + end + + protected + + # @!visibility private + def ns_initialize(value, opts) + value = yield if block_given? + init_obligation + self.observers = Collection::CopyOnWriteObserverSet.new + set_deref_options(opts) + + @state = :pending + if value != NULL + ns_complete_without_notification(true, value, nil) + end + end + + # @!visibility private + def safe_execute(task, args = []) + if compare_and_set_state(:processing, :pending) + success, val, reason = SafeTaskExecutor.new(task, rescue_exception: true).execute(*@args) + complete(success, val, reason) + yield(success, val, reason) if block_given? + end + end + + # @!visibility private + def complete(success, value, reason) + complete_without_notification(success, value, reason) + notify_observers(self.value, reason) + self + end + + # @!visibility private + def complete_without_notification(success, value, reason) + synchronize { ns_complete_without_notification(success, value, reason) } + self + end + + # @!visibility private + def notify_observers(value, reason) + observers.notify_and_delete_observers{ [Time.now, value, reason] } + end + + # @!visibility private + def ns_complete_without_notification(success, value, reason) + raise MultipleAssignmentError if [:fulfilled, :rejected].include? @state + set_state(success, value, reason) + event.set + end + + # @!visibility private + def check_for_block_or_value!(block_given, value) # :nodoc: + if (block_given && value != NULL) || (! block_given && value == NULL) + raise ArgumentError.new('must set with either a value or a block') + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/map.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/map.rb new file mode 100644 index 0000000000000..601e365042570 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/map.rb @@ -0,0 +1,350 @@ +require 'thread' +require 'concurrent/constants' +require 'concurrent/utility/engine' + +module Concurrent + # @!visibility private + module Collection + + # @!visibility private + MapImplementation = case + when Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + # noinspection RubyResolve + JRubyMapBackend + when Concurrent.on_cruby? + require 'concurrent/collection/map/mri_map_backend' + MriMapBackend + when Concurrent.on_truffleruby? + if defined?(::TruffleRuby::ConcurrentMap) + require 'concurrent/collection/map/truffleruby_map_backend' + TruffleRubyMapBackend + else + require 'concurrent/collection/map/synchronized_map_backend' + SynchronizedMapBackend + end + else + warn 'Concurrent::Map: unsupported Ruby engine, using a fully synchronized Concurrent::Map implementation' + require 'concurrent/collection/map/synchronized_map_backend' + SynchronizedMapBackend + end + end + + # `Concurrent::Map` is a hash-like object and should have much better performance + # characteristics, especially under high concurrency, than `Concurrent::Hash`. + # However, `Concurrent::Map `is not strictly semantically equivalent to a ruby `Hash` + # -- for instance, it does not necessarily retain ordering by insertion time as `Hash` + # does. For most uses it should do fine though, and we recommend you consider + # `Concurrent::Map` instead of `Concurrent::Hash` for your concurrency-safe hash needs. + class Map < Collection::MapImplementation + + # @!macro map.atomic_method + # This method is atomic. + + # @!macro map.atomic_method_with_block + # This method is atomic. + # @note Atomic methods taking a block do not allow the `self` instance + # to be used within the block. Doing so will cause a deadlock. + + # @!method []=(key, value) + # Set a value with key + # @param [Object] key + # @param [Object] value + # @return [Object] the new value + + # @!method compute_if_absent(key) + # Compute and store new value for key if the key is absent. + # @param [Object] key + # @yield new value + # @yieldreturn [Object] new value + # @return [Object] new value or current value + # @!macro map.atomic_method_with_block + + # @!method compute_if_present(key) + # Compute and store new value for key if the key is present. + # @param [Object] key + # @yield new value + # @yieldparam old_value [Object] + # @yieldreturn [Object, nil] new value, when nil the key is removed + # @return [Object, nil] new value or nil + # @!macro map.atomic_method_with_block + + # @!method compute(key) + # Compute and store new value for key. + # @param [Object] key + # @yield compute new value from old one + # @yieldparam old_value [Object, nil] old_value, or nil when key is absent + # @yieldreturn [Object, nil] new value, when nil the key is removed + # @return [Object, nil] new value or nil + # @!macro map.atomic_method_with_block + + # @!method merge_pair(key, value) + # If the key is absent, the value is stored, otherwise new value is + # computed with a block. + # @param [Object] key + # @param [Object] value + # @yield compute new value from old one + # @yieldparam old_value [Object] old value + # @yieldreturn [Object, nil] new value, when nil the key is removed + # @return [Object, nil] new value or nil + # @!macro map.atomic_method_with_block + + # @!method replace_pair(key, old_value, new_value) + # Replaces old_value with new_value if key exists and current value + # matches old_value + # @param [Object] key + # @param [Object] old_value + # @param [Object] new_value + # @return [true, false] true if replaced + # @!macro map.atomic_method + + # @!method replace_if_exists(key, new_value) + # Replaces current value with new_value if key exists + # @param [Object] key + # @param [Object] new_value + # @return [Object, nil] old value or nil + # @!macro map.atomic_method + + # @!method get_and_set(key, value) + # Get the current value under key and set new value. + # @param [Object] key + # @param [Object] value + # @return [Object, nil] old value or nil when the key was absent + # @!macro map.atomic_method + + # @!method delete(key) + # Delete key and its value. + # @param [Object] key + # @return [Object, nil] old value or nil when the key was absent + # @!macro map.atomic_method + + # @!method delete_pair(key, value) + # Delete pair and its value if current value equals the provided value. + # @param [Object] key + # @param [Object] value + # @return [true, false] true if deleted + # @!macro map.atomic_method + + # NonConcurrentMapBackend handles default_proc natively + unless defined?(Collection::NonConcurrentMapBackend) and self < Collection::NonConcurrentMapBackend + + # @param [Hash, nil] options options to set the :initial_capacity or :load_factor. Ignored on some Rubies. + # @param [Proc] default_proc Optional block to compute the default value if the key is not set, like `Hash#default_proc` + def initialize(options = nil, &default_proc) + if options.kind_of?(::Hash) + validate_options_hash!(options) + else + options = nil + end + + super(options) + @default_proc = default_proc + end + + # Get a value with key + # @param [Object] key + # @return [Object] the value + def [](key) + if value = super # non-falsy value is an existing mapping, return it right away + value + # re-check is done with get_or_default(key, NULL) instead of a simple !key?(key) in order to avoid a race condition, whereby by the time the current thread gets to the key?(key) call + # a key => value mapping might have already been created by a different thread (key?(key) would then return true, this elsif branch wouldn't be taken and an incorrent +nil+ value + # would be returned) + # note: nil == value check is not technically necessary + elsif @default_proc && nil == value && NULL == (value = get_or_default(key, NULL)) + @default_proc.call(self, key) + else + value + end + end + end + + alias_method :get, :[] + alias_method :put, :[]= + + # Get a value with key, or default_value when key is absent, + # or fail when no default_value is given. + # @param [Object] key + # @param [Object] default_value + # @yield default value for a key + # @yieldparam key [Object] + # @yieldreturn [Object] default value + # @return [Object] the value or default value + # @raise [KeyError] when key is missing and no default_value is provided + # @!macro map_method_not_atomic + # @note The "fetch-then-act" methods of `Map` are not atomic. `Map` is intended + # to be use as a concurrency primitive with strong happens-before + # guarantees. It is not intended to be used as a high-level abstraction + # supporting complex operations. All read and write operations are + # thread safe, but no guarantees are made regarding race conditions + # between the fetch operation and yielding to the block. Additionally, + # this method does not support recursion. This is due to internal + # constraints that are very unlikely to change in the near future. + def fetch(key, default_value = NULL) + if NULL != (value = get_or_default(key, NULL)) + value + elsif block_given? + yield key + elsif NULL != default_value + default_value + else + raise_fetch_no_key + end + end + + # Fetch value with key, or store default value when key is absent, + # or fail when no default_value is given. This is a two step operation, + # therefore not atomic. The store can overwrite other concurrently + # stored value. + # @param [Object] key + # @param [Object] default_value + # @yield default value for a key + # @yieldparam key [Object] + # @yieldreturn [Object] default value + # @return [Object] the value or default value + def fetch_or_store(key, default_value = NULL) + fetch(key) do + put(key, block_given? ? yield(key) : (NULL == default_value ? raise_fetch_no_key : default_value)) + end + end + + # Insert value into map with key if key is absent in one atomic step. + # @param [Object] key + # @param [Object] value + # @return [Object, nil] the previous value when key was present or nil when there was no key + def put_if_absent(key, value) + computed = false + result = compute_if_absent(key) do + computed = true + value + end + computed ? nil : result + end unless method_defined?(:put_if_absent) + + # Is the value stored in the map. Iterates over all values. + # @param [Object] value + # @return [true, false] + def value?(value) + each_value do |v| + return true if value.equal?(v) + end + false + end + + # All keys + # @return [::Array] keys + def keys + arr = [] + each_pair { |k, v| arr << k } + arr + end unless method_defined?(:keys) + + # All values + # @return [::Array] values + def values + arr = [] + each_pair { |k, v| arr << v } + arr + end unless method_defined?(:values) + + # Iterates over each key. + # @yield for each key in the map + # @yieldparam key [Object] + # @return [self] + # @!macro map.atomic_method_with_block + def each_key + each_pair { |k, v| yield k } + end unless method_defined?(:each_key) + + # Iterates over each value. + # @yield for each value in the map + # @yieldparam value [Object] + # @return [self] + # @!macro map.atomic_method_with_block + def each_value + each_pair { |k, v| yield v } + end unless method_defined?(:each_value) + + # Iterates over each key value pair. + # @yield for each key value pair in the map + # @yieldparam key [Object] + # @yieldparam value [Object] + # @return [self] + # @!macro map.atomic_method_with_block + def each_pair + return enum_for :each_pair unless block_given? + super + end + + alias_method :each, :each_pair unless method_defined?(:each) + + # Find key of a value. + # @param [Object] value + # @return [Object, nil] key or nil when not found + def key(value) + each_pair { |k, v| return k if v == value } + nil + end unless method_defined?(:key) + + # Is map empty? + # @return [true, false] + def empty? + each_pair { |k, v| return false } + true + end unless method_defined?(:empty?) + + # The size of map. + # @return [Integer] size + def size + count = 0 + each_pair { |k, v| count += 1 } + count + end unless method_defined?(:size) + + # @!visibility private + def marshal_dump + raise TypeError, "can't dump hash with default proc" if @default_proc + h = {} + each_pair { |k, v| h[k] = v } + h + end + + # @!visibility private + def marshal_load(hash) + initialize + populate_from(hash) + end + + undef :freeze + + # @!visibility private + def inspect + format '%s entries=%d default_proc=%s>', to_s[0..-2], size.to_s, @default_proc.inspect + end + + private + + def raise_fetch_no_key + raise KeyError, 'key not found' + end + + def initialize_copy(other) + super + populate_from(other) + end + + def populate_from(hash) + hash.each_pair { |k, v| self[k] = v } + self + end + + def validate_options_hash!(options) + if (initial_capacity = options[:initial_capacity]) && (!initial_capacity.kind_of?(Integer) || initial_capacity < 0) + raise ArgumentError, ":initial_capacity must be a positive Integer" + end + if (load_factor = options[:load_factor]) && (!load_factor.kind_of?(Numeric) || load_factor <= 0 || load_factor > 1) + raise ArgumentError, ":load_factor must be a number between 0 and 1" + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/maybe.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/maybe.rb new file mode 100644 index 0000000000000..317c82b86fa2a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/maybe.rb @@ -0,0 +1,229 @@ +require 'concurrent/synchronization/object' + +module Concurrent + + # A `Maybe` encapsulates an optional value. A `Maybe` either contains a value + # of (represented as `Just`), or it is empty (represented as `Nothing`). Using + # `Maybe` is a good way to deal with errors or exceptional cases without + # resorting to drastic measures such as exceptions. + # + # `Maybe` is a replacement for the use of `nil` with better type checking. + # + # For compatibility with {Concurrent::Concern::Obligation} the predicate and + # accessor methods are aliased as `fulfilled?`, `rejected?`, `value`, and + # `reason`. + # + # ## Motivation + # + # A common pattern in languages with pattern matching, such as Erlang and + # Haskell, is to return *either* a value *or* an error from a function + # Consider this Erlang code: + # + # ```erlang + # case file:consult("data.dat") of + # {ok, Terms} -> do_something_useful(Terms); + # {error, Reason} -> lager:error(Reason) + # end. + # ``` + # + # In this example the standard library function `file:consult` returns a + # [tuple](http://erlang.org/doc/reference_manual/data_types.html#id69044) + # with two elements: an [atom](http://erlang.org/doc/reference_manual/data_types.html#id64134) + # (similar to a ruby symbol) and a variable containing ancillary data. On + # success it returns the atom `ok` and the data from the file. On failure it + # returns `error` and a string with an explanation of the problem. With this + # pattern there is no ambiguity regarding success or failure. If the file is + # empty the return value cannot be misinterpreted as an error. And when an + # error occurs the return value provides useful information. + # + # In Ruby we tend to return `nil` when an error occurs or else we raise an + # exception. Both of these idioms are problematic. Returning `nil` is + # ambiguous because `nil` may also be a valid value. It also lacks + # information pertaining to the nature of the error. Raising an exception + # is both expensive and usurps the normal flow of control. All of these + # problems can be solved with the use of a `Maybe`. + # + # A `Maybe` is unambiguous with regard to whether or not it contains a value. + # When `Just` it contains a value, when `Nothing` it does not. When `Just` + # the value it contains may be `nil`, which is perfectly valid. When + # `Nothing` the reason for the lack of a value is contained as well. The + # previous Erlang example can be duplicated in Ruby in a principled way by + # having functions return `Maybe` objects: + # + # ```ruby + # result = MyFileUtils.consult("data.dat") # returns a Maybe + # if result.just? + # do_something_useful(result.value) # or result.just + # else + # logger.error(result.reason) # or result.nothing + # end + # ``` + # + # @example Returning a Maybe from a Function + # module MyFileUtils + # def self.consult(path) + # file = File.open(path, 'r') + # Concurrent::Maybe.just(file.read) + # rescue => ex + # return Concurrent::Maybe.nothing(ex) + # ensure + # file.close if file + # end + # end + # + # maybe = MyFileUtils.consult('bogus.file') + # maybe.just? #=> false + # maybe.nothing? #=> true + # maybe.reason #=> # + # + # maybe = MyFileUtils.consult('README.md') + # maybe.just? #=> true + # maybe.nothing? #=> false + # maybe.value #=> "# Concurrent Ruby\n[![Gem Version..." + # + # @example Using Maybe with a Block + # result = Concurrent::Maybe.from do + # Client.find(10) # Client is an ActiveRecord model + # end + # + # # -- if the record was found + # result.just? #=> true + # result.value #=> # + # + # # -- if the record was not found + # result.just? #=> false + # result.reason #=> ActiveRecord::RecordNotFound + # + # @example Using Maybe with the Null Object Pattern + # # In a Rails controller... + # result = ClientService.new(10).find # returns a Maybe + # render json: result.or(NullClient.new) + # + # @see https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html Haskell Data.Maybe + # @see https://github.com/purescript/purescript-maybe/blob/master/docs/Data.Maybe.md PureScript Data.Maybe + class Maybe < Synchronization::Object + include Comparable + safe_initialization! + + # Indicates that the given attribute has not been set. + # When `Just` the {#nothing} getter will return `NONE`. + # When `Nothing` the {#just} getter will return `NONE`. + NONE = ::Object.new.freeze + + # The value of a `Maybe` when `Just`. Will be `NONE` when `Nothing`. + attr_reader :just + + # The reason for the `Maybe` when `Nothing`. Will be `NONE` when `Just`. + attr_reader :nothing + + private_class_method :new + + # Create a new `Maybe` using the given block. + # + # Runs the given block passing all function arguments to the block as block + # arguments. If the block runs to completion without raising an exception + # a new `Just` is created with the value set to the return value of the + # block. If the block raises an exception a new `Nothing` is created with + # the reason being set to the raised exception. + # + # @param [Array] args Zero or more arguments to pass to the block. + # @yield The block from which to create a new `Maybe`. + # @yieldparam [Array] args Zero or more block arguments passed as + # arguments to the function. + # + # @return [Maybe] The newly created object. + # + # @raise [ArgumentError] when no block given. + def self.from(*args) + raise ArgumentError.new('no block given') unless block_given? + begin + value = yield(*args) + return new(value, NONE) + rescue => ex + return new(NONE, ex) + end + end + + # Create a new `Just` with the given value. + # + # @param [Object] value The value to set for the new `Maybe` object. + # + # @return [Maybe] The newly created object. + def self.just(value) + return new(value, NONE) + end + + # Create a new `Nothing` with the given (optional) reason. + # + # @param [Exception] error The reason to set for the new `Maybe` object. + # When given a string a new `StandardError` will be created with the + # argument as the message. When no argument is given a new + # `StandardError` with an empty message will be created. + # + # @return [Maybe] The newly created object. + def self.nothing(error = '') + if error.is_a?(Exception) + nothing = error + else + nothing = StandardError.new(error.to_s) + end + return new(NONE, nothing) + end + + # Is this `Maybe` a `Just` (successfully fulfilled with a value)? + # + # @return [Boolean] True if `Just` or false if `Nothing`. + def just? + ! nothing? + end + alias :fulfilled? :just? + + # Is this `Maybe` a `nothing` (rejected with an exception upon fulfillment)? + # + # @return [Boolean] True if `Nothing` or false if `Just`. + def nothing? + @nothing != NONE + end + alias :rejected? :nothing? + + alias :value :just + + alias :reason :nothing + + # Comparison operator. + # + # @return [Integer] 0 if self and other are both `Nothing`; + # -1 if self is `Nothing` and other is `Just`; + # 1 if self is `Just` and other is nothing; + # `self.just <=> other.just` if both self and other are `Just`. + def <=>(other) + if nothing? + other.nothing? ? 0 : -1 + else + other.nothing? ? 1 : just <=> other.just + end + end + + # Return either the value of self or the given default value. + # + # @return [Object] The value of self when `Just`; else the given default. + def or(other) + just? ? just : other + end + + private + + # Create a new `Maybe` with the given attributes. + # + # @param [Object] just The value when `Just` else `NONE`. + # @param [Exception, Object] nothing The exception when `Nothing` else `NONE`. + # + # @return [Maybe] The new `Maybe`. + # + # @!visibility private + def initialize(just, nothing) + @just = just + @nothing = nothing + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mutable_struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mutable_struct.rb new file mode 100644 index 0000000000000..5d0e9b9af59e0 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mutable_struct.rb @@ -0,0 +1,239 @@ +require 'concurrent/synchronization/abstract_struct' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # An thread-safe variation of Ruby's standard `Struct`. Values can be set at + # construction or safely changed at any time during the object's lifecycle. + # + # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` + module MutableStruct + include Synchronization::AbstractStruct + + # @!macro struct_new + # + # Factory for creating new struct classes. + # + # ``` + # new([class_name] [, member_name]+>) -> StructClass click to toggle source + # new([class_name] [, member_name]+>) {|StructClass| block } -> StructClass + # new(value, ...) -> obj + # StructClass[value, ...] -> obj + # ``` + # + # The first two forms are used to create a new struct subclass `class_name` + # that can contain a value for each member_name . This subclass can be + # used to create instances of the structure like any other Class . + # + # If the `class_name` is omitted an anonymous struct class will be created. + # Otherwise, the name of this struct will appear as a constant in the struct class, + # so it must be unique for all structs under this base class and must start with a + # capital letter. Assigning a struct class to a constant also gives the class + # the name of the constant. + # + # If a block is given it will be evaluated in the context of `StructClass`, passing + # the created class as a parameter. This is the recommended way to customize a struct. + # Subclassing an anonymous struct creates an extra anonymous class that will never be used. + # + # The last two forms create a new instance of a struct subclass. The number of value + # parameters must be less than or equal to the number of attributes defined for the + # struct. Unset parameters default to nil. Passing more parameters than number of attributes + # will raise an `ArgumentError`. + # + # @see http://ruby-doc.org/core/Struct.html#method-c-new Ruby standard library `Struct#new` + + # @!macro struct_values + # + # Returns the values for this struct as an Array. + # + # @return [Array] the values for this struct + # + def values + synchronize { ns_values } + end + alias_method :to_a, :values + + # @!macro struct_values_at + # + # Returns the struct member values for each selector as an Array. + # + # A selector may be either an Integer offset or a Range of offsets (as in `Array#values_at`). + # + # @param [Fixnum, Range] indexes the index(es) from which to obatin the values (in order) + def values_at(*indexes) + synchronize { ns_values_at(indexes) } + end + + # @!macro struct_inspect + # + # Describe the contents of this struct in a string. + # + # @return [String] the contents of this struct in a string + def inspect + synchronize { ns_inspect } + end + alias_method :to_s, :inspect + + # @!macro struct_merge + # + # Returns a new struct containing the contents of `other` and the contents + # of `self`. If no block is specified, the value for entries with duplicate + # keys will be that of `other`. Otherwise the value for each duplicate key + # is determined by calling the block with the key, its value in `self` and + # its value in `other`. + # + # @param [Hash] other the hash from which to set the new values + # @yield an options block for resolving duplicate keys + # @yieldparam [String, Symbol] member the name of the member which is duplicated + # @yieldparam [Object] selfvalue the value of the member in `self` + # @yieldparam [Object] othervalue the value of the member in `other` + # + # @return [Synchronization::AbstractStruct] a new struct with the new values + # + # @raise [ArgumentError] of given a member that is not defined in the struct + def merge(other, &block) + synchronize { ns_merge(other, &block) } + end + + # @!macro struct_to_h + # + # Returns a hash containing the names and values for the struct’s members. + # + # @return [Hash] the names and values for the struct’s members + def to_h + synchronize { ns_to_h } + end + + # @!macro struct_get + # + # Attribute Reference + # + # @param [Symbol, String, Integer] member the string or symbol name of the member + # for which to obtain the value or the member's index + # + # @return [Object] the value of the given struct member or the member at the given index. + # + # @raise [NameError] if the member does not exist + # @raise [IndexError] if the index is out of range. + def [](member) + synchronize { ns_get(member) } + end + + # @!macro struct_equality + # + # Equality + # + # @return [Boolean] true if other has the same struct subclass and has + # equal member values (according to `Object#==`) + def ==(other) + synchronize { ns_equality(other) } + end + + # @!macro struct_each + # + # Yields the value of each struct member in order. If no block is given + # an enumerator is returned. + # + # @yield the operation to be performed on each struct member + # @yieldparam [Object] value each struct value (in order) + def each(&block) + return enum_for(:each) unless block_given? + synchronize { ns_each(&block) } + end + + # @!macro struct_each_pair + # + # Yields the name and value of each struct member in order. If no block is + # given an enumerator is returned. + # + # @yield the operation to be performed on each struct member/value pair + # @yieldparam [Object] member each struct member (in order) + # @yieldparam [Object] value each struct value (in order) + def each_pair(&block) + return enum_for(:each_pair) unless block_given? + synchronize { ns_each_pair(&block) } + end + + # @!macro struct_select + # + # Yields each member value from the struct to the block and returns an Array + # containing the member values from the struct for which the given block + # returns a true value (equivalent to `Enumerable#select`). + # + # @yield the operation to be performed on each struct member + # @yieldparam [Object] value each struct value (in order) + # + # @return [Array] an array containing each value for which the block returns true + def select(&block) + return enum_for(:select) unless block_given? + synchronize { ns_select(&block) } + end + + # @!macro struct_set + # + # Attribute Assignment + # + # Sets the value of the given struct member or the member at the given index. + # + # @param [Symbol, String, Integer] member the string or symbol name of the member + # for which to obtain the value or the member's index + # + # @return [Object] the value of the given struct member or the member at the given index. + # + # @raise [NameError] if the name does not exist + # @raise [IndexError] if the index is out of range. + def []=(member, value) + if member.is_a? Integer + length = synchronize { @values.length } + if member >= length + raise IndexError.new("offset #{member} too large for struct(size:#{length})") + end + synchronize { @values[member] = value } + else + send("#{member}=", value) + end + rescue NoMethodError + raise NameError.new("no member '#{member}' in struct") + end + + private + + # @!visibility private + def initialize_copy(original) + synchronize do + super(original) + ns_initialize_copy + end + end + + # @!macro struct_new + def self.new(*args, &block) + clazz_name = nil + if args.length == 0 + raise ArgumentError.new('wrong number of arguments (0 for 1+)') + elsif args.length > 0 && args.first.is_a?(String) + clazz_name = args.shift + end + FACTORY.define_struct(clazz_name, args, &block) + end + + FACTORY = Class.new(Synchronization::LockableObject) do + def define_struct(name, members, &block) + synchronize do + clazz = Synchronization::AbstractStruct.define_struct_class(MutableStruct, Synchronization::LockableObject, name, members, &block) + members.each_with_index do |member, index| + clazz.send :remove_method, member + clazz.send(:define_method, member) do + synchronize { @values[index] } + end + clazz.send(:define_method, "#{member}=") do |value| + synchronize { @values[index] = value } + end + end + clazz + end + end + end.new + private_constant :FACTORY + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mvar.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mvar.rb new file mode 100644 index 0000000000000..dfc41950cf85f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/mvar.rb @@ -0,0 +1,242 @@ +require 'concurrent/concern/dereferenceable' +require 'concurrent/synchronization/object' + +module Concurrent + + # An `MVar` is a synchronized single element container. They are empty or + # contain one item. Taking a value from an empty `MVar` blocks, as does + # putting a value into a full one. You can either think of them as blocking + # queue of length one, or a special kind of mutable variable. + # + # On top of the fundamental `#put` and `#take` operations, we also provide a + # `#mutate` that is atomic with respect to operations on the same instance. + # These operations all support timeouts. + # + # We also support non-blocking operations `#try_put!` and `#try_take!`, a + # `#set!` that ignores existing values, a `#value` that returns the value + # without removing it or returns `MVar::EMPTY`, and a `#modify!` that yields + # `MVar::EMPTY` if the `MVar` is empty and can be used to set `MVar::EMPTY`. + # You shouldn't use these operations in the first instance. + # + # `MVar` is a [Dereferenceable](Dereferenceable). + # + # `MVar` is related to M-structures in Id, `MVar` in Haskell and `SyncVar` in Scala. + # + # Note that unlike the original Haskell paper, our `#take` is blocking. This is how + # Haskell and Scala do it today. + # + # @!macro copy_options + # + # ## See Also + # + # 1. P. Barth, R. Nikhil, and Arvind. [M-Structures: Extending a parallel, non- strict, functional language with state](http://dl.acm.org/citation.cfm?id=652538). In Proceedings of the 5th + # ACM Conference on Functional Programming Languages and Computer Architecture (FPCA), 1991. + # + # 2. S. Peyton Jones, A. Gordon, and S. Finne. [Concurrent Haskell](http://dl.acm.org/citation.cfm?id=237794). + # In Proceedings of the 23rd Symposium on Principles of Programming Languages + # (PoPL), 1996. + class MVar < Synchronization::Object + include Concern::Dereferenceable + safe_initialization! + + # Unique value that represents that an `MVar` was empty + EMPTY = ::Object.new + + # Unique value that represents that an `MVar` timed out before it was able + # to produce a value. + TIMEOUT = ::Object.new + + # Create a new `MVar`, either empty or with an initial value. + # + # @param [Hash] opts the options controlling how the future will be processed + # + # @!macro deref_options + def initialize(value = EMPTY, opts = {}) + @value = value + @mutex = Mutex.new + @empty_condition = ConditionVariable.new + @full_condition = ConditionVariable.new + set_deref_options(opts) + end + + # Remove the value from an `MVar`, leaving it empty, and blocking if there + # isn't a value. A timeout can be set to limit the time spent blocked, in + # which case it returns `TIMEOUT` if the time is exceeded. + # @return [Object] the value that was taken, or `TIMEOUT` + def take(timeout = nil) + @mutex.synchronize do + wait_for_full(timeout) + + # If we timed out we'll still be empty + if unlocked_full? + value = @value + @value = EMPTY + @empty_condition.signal + apply_deref_options(value) + else + TIMEOUT + end + end + end + + # acquires lock on the from an `MVAR`, yields the value to provided block, + # and release lock. A timeout can be set to limit the time spent blocked, + # in which case it returns `TIMEOUT` if the time is exceeded. + # @return [Object] the value returned by the block, or `TIMEOUT` + def borrow(timeout = nil) + @mutex.synchronize do + wait_for_full(timeout) + + # if we timeoud out we'll still be empty + if unlocked_full? + yield @value + else + TIMEOUT + end + end + end + + # Put a value into an `MVar`, blocking if there is already a value until + # it is empty. A timeout can be set to limit the time spent blocked, in + # which case it returns `TIMEOUT` if the time is exceeded. + # @return [Object] the value that was put, or `TIMEOUT` + def put(value, timeout = nil) + @mutex.synchronize do + wait_for_empty(timeout) + + # If we timed out we won't be empty + if unlocked_empty? + @value = value + @full_condition.signal + apply_deref_options(value) + else + TIMEOUT + end + end + end + + # Atomically `take`, yield the value to a block for transformation, and then + # `put` the transformed value. Returns the transformed value. A timeout can + # be set to limit the time spent blocked, in which case it returns `TIMEOUT` + # if the time is exceeded. + # @return [Object] the transformed value, or `TIMEOUT` + def modify(timeout = nil) + raise ArgumentError.new('no block given') unless block_given? + + @mutex.synchronize do + wait_for_full(timeout) + + # If we timed out we'll still be empty + if unlocked_full? + value = @value + @value = yield value + @full_condition.signal + apply_deref_options(value) + else + TIMEOUT + end + end + end + + # Non-blocking version of `take`, that returns `EMPTY` instead of blocking. + def try_take! + @mutex.synchronize do + if unlocked_full? + value = @value + @value = EMPTY + @empty_condition.signal + apply_deref_options(value) + else + EMPTY + end + end + end + + # Non-blocking version of `put`, that returns whether or not it was successful. + def try_put!(value) + @mutex.synchronize do + if unlocked_empty? + @value = value + @full_condition.signal + true + else + false + end + end + end + + # Non-blocking version of `put` that will overwrite an existing value. + def set!(value) + @mutex.synchronize do + old_value = @value + @value = value + @full_condition.signal + apply_deref_options(old_value) + end + end + + # Non-blocking version of `modify` that will yield with `EMPTY` if there is no value yet. + def modify! + raise ArgumentError.new('no block given') unless block_given? + + @mutex.synchronize do + value = @value + @value = yield value + if unlocked_empty? + @empty_condition.signal + else + @full_condition.signal + end + apply_deref_options(value) + end + end + + # Returns if the `MVar` is currently empty. + def empty? + @mutex.synchronize { @value == EMPTY } + end + + # Returns if the `MVar` currently contains a value. + def full? + !empty? + end + + protected + + def synchronize(&block) + @mutex.synchronize(&block) + end + + private + + def unlocked_empty? + @value == EMPTY + end + + def unlocked_full? + ! unlocked_empty? + end + + def wait_for_full(timeout) + wait_while(@full_condition, timeout) { unlocked_empty? } + end + + def wait_for_empty(timeout) + wait_while(@empty_condition, timeout) { unlocked_full? } + end + + def wait_while(condition, timeout) + if timeout.nil? + while yield + condition.wait(@mutex) + end + else + stop = Concurrent.monotonic_time + timeout + while yield && timeout > 0.0 + condition.wait(@mutex, timeout) + timeout = stop - Concurrent.monotonic_time + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/options.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/options.rb new file mode 100644 index 0000000000000..bdd22a9df15d4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/options.rb @@ -0,0 +1,42 @@ +require 'concurrent/configuration' + +module Concurrent + + # @!visibility private + module Options + + # Get the requested `Executor` based on the values set in the options hash. + # + # @param [Hash] opts the options defining the requested executor + # @option opts [Executor] :executor when set use the given `Executor` instance. + # Three special values are also supported: `:fast` returns the global fast executor, + # `:io` returns the global io executor, and `:immediate` returns a new + # `ImmediateExecutor` object. + # + # @return [Executor, nil] the requested thread pool, or nil when no option specified + # + # @!visibility private + def self.executor_from_options(opts = {}) # :nodoc: + if identifier = opts.fetch(:executor, nil) + executor(identifier) + else + nil + end + end + + def self.executor(executor_identifier) + case executor_identifier + when :fast + Concurrent.global_fast_executor + when :io + Concurrent.global_io_executor + when :immediate + Concurrent.global_immediate_executor + when Concurrent::ExecutorService + executor_identifier + else + raise ArgumentError, "executor not recognized by '#{executor_identifier}'" + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promise.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promise.rb new file mode 100644 index 0000000000000..ccc47dd628c8d --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promise.rb @@ -0,0 +1,580 @@ +require 'thread' +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/ivar' +require 'concurrent/executor/safe_task_executor' + +require 'concurrent/options' + +module Concurrent + + PromiseExecutionError = Class.new(StandardError) + + # Promises are inspired by the JavaScript [Promises/A](http://wiki.commonjs.org/wiki/Promises/A) + # and [Promises/A+](http://promises-aplus.github.io/promises-spec/) specifications. + # + # > A promise represents the eventual value returned from the single + # > completion of an operation. + # + # Promises are similar to futures and share many of the same behaviours. + # Promises are far more robust, however. Promises can be chained in a tree + # structure where each promise may have zero or more children. Promises are + # chained using the `then` method. The result of a call to `then` is always + # another promise. Promises are resolved asynchronously (with respect to the + # main thread) but in a strict order: parents are guaranteed to be resolved + # before their children, children before their younger siblings. The `then` + # method takes two parameters: an optional block to be executed upon parent + # resolution and an optional callable to be executed upon parent failure. The + # result of each promise is passed to each of its children upon resolution. + # When a promise is rejected all its children will be summarily rejected and + # will receive the reason. + # + # Promises have several possible states: *:unscheduled*, *:pending*, + # *:processing*, *:rejected*, or *:fulfilled*. These are also aggregated as + # `#incomplete?` and `#complete?`. When a Promise is created it is set to + # *:unscheduled*. Once the `#execute` method is called the state becomes + # *:pending*. Once a job is pulled from the thread pool's queue and is given + # to a thread for processing (often immediately upon `#post`) the state + # becomes *:processing*. The future will remain in this state until processing + # is complete. A future that is in the *:unscheduled*, *:pending*, or + # *:processing* is considered `#incomplete?`. A `#complete?` Promise is either + # *:rejected*, indicating that an exception was thrown during processing, or + # *:fulfilled*, indicating success. If a Promise is *:fulfilled* its `#value` + # will be updated to reflect the result of the operation. If *:rejected* the + # `reason` will be updated with a reference to the thrown exception. The + # predicate methods `#unscheduled?`, `#pending?`, `#rejected?`, and + # `#fulfilled?` can be called at any time to obtain the state of the Promise, + # as can the `#state` method, which returns a symbol. + # + # Retrieving the value of a promise is done through the `value` (alias: + # `deref`) method. Obtaining the value of a promise is a potentially blocking + # operation. When a promise is *rejected* a call to `value` will return `nil` + # immediately. When a promise is *fulfilled* a call to `value` will + # immediately return the current value. When a promise is *pending* a call to + # `value` will block until the promise is either *rejected* or *fulfilled*. A + # *timeout* value can be passed to `value` to limit how long the call will + # block. If `nil` the call will block indefinitely. If `0` the call will not + # block. Any other integer or float value will indicate the maximum number of + # seconds to block. + # + # Promises run on the global thread pool. + # + # @!macro copy_options + # + # ### Examples + # + # Start by requiring promises + # + # ```ruby + # require 'concurrent/promise' + # ``` + # + # Then create one + # + # ```ruby + # p = Concurrent::Promise.execute do + # # do something + # 42 + # end + # ``` + # + # Promises can be chained using the `then` method. The `then` method accepts a + # block and an executor, to be executed on fulfillment, and a callable argument to be executed + # on rejection. The result of the each promise is passed as the block argument + # to chained promises. + # + # ```ruby + # p = Concurrent::Promise.new{10}.then{|x| x * 2}.then{|result| result - 10 }.execute + # ``` + # + # And so on, and so on, and so on... + # + # ```ruby + # p = Concurrent::Promise.fulfill(20). + # then{|result| result - 10 }. + # then{|result| result * 3 }. + # then(executor: different_executor){|result| result % 5 }.execute + # ``` + # + # The initial state of a newly created Promise depends on the state of its parent: + # - if parent is *unscheduled* the child will be *unscheduled* + # - if parent is *pending* the child will be *pending* + # - if parent is *fulfilled* the child will be *pending* + # - if parent is *rejected* the child will be *pending* (but will ultimately be *rejected*) + # + # Promises are executed asynchronously from the main thread. By the time a + # child Promise finishes intialization it may be in a different state than its + # parent (by the time a child is created its parent may have completed + # execution and changed state). Despite being asynchronous, however, the order + # of execution of Promise objects in a chain (or tree) is strictly defined. + # + # There are multiple ways to create and execute a new `Promise`. Both ways + # provide identical behavior: + # + # ```ruby + # # create, operate, then execute + # p1 = Concurrent::Promise.new{ "Hello World!" } + # p1.state #=> :unscheduled + # p1.execute + # + # # create and immediately execute + # p2 = Concurrent::Promise.new{ "Hello World!" }.execute + # + # # execute during creation + # p3 = Concurrent::Promise.execute{ "Hello World!" } + # ``` + # + # Once the `execute` method is called a `Promise` becomes `pending`: + # + # ```ruby + # p = Concurrent::Promise.execute{ "Hello, world!" } + # p.state #=> :pending + # p.pending? #=> true + # ``` + # + # Wait a little bit, and the promise will resolve and provide a value: + # + # ```ruby + # p = Concurrent::Promise.execute{ "Hello, world!" } + # sleep(0.1) + # + # p.state #=> :fulfilled + # p.fulfilled? #=> true + # p.value #=> "Hello, world!" + # ``` + # + # If an exception occurs, the promise will be rejected and will provide + # a reason for the rejection: + # + # ```ruby + # p = Concurrent::Promise.execute{ raise StandardError.new("Here comes the Boom!") } + # sleep(0.1) + # + # p.state #=> :rejected + # p.rejected? #=> true + # p.reason #=> "#" + # ``` + # + # #### Rejection + # + # When a promise is rejected all its children will be rejected and will + # receive the rejection `reason` as the rejection callable parameter: + # + # ```ruby + # p = Concurrent::Promise.execute { Thread.pass; raise StandardError } + # + # c1 = p.then(-> reason { 42 }) + # c2 = p.then(-> reason { raise 'Boom!' }) + # + # c1.wait.state #=> :fulfilled + # c1.value #=> 45 + # c2.wait.state #=> :rejected + # c2.reason #=> # + # ``` + # + # Once a promise is rejected it will continue to accept children that will + # receive immediately rejection (they will be executed asynchronously). + # + # #### Aliases + # + # The `then` method is the most generic alias: it accepts a block to be + # executed upon parent fulfillment and a callable to be executed upon parent + # rejection. At least one of them should be passed. The default block is `{ + # |result| result }` that fulfills the child with the parent value. The + # default callable is `{ |reason| raise reason }` that rejects the child with + # the parent reason. + # + # - `on_success { |result| ... }` is the same as `then {|result| ... }` + # - `rescue { |reason| ... }` is the same as `then(Proc.new { |reason| ... } )` + # - `rescue` is aliased by `catch` and `on_error` + class Promise < IVar + + # Initialize a new Promise with the provided options. + # + # @!macro executor_and_deref_options + # + # @!macro promise_init_options + # + # @option opts [Promise] :parent the parent `Promise` when building a chain/tree + # @option opts [Proc] :on_fulfill fulfillment handler + # @option opts [Proc] :on_reject rejection handler + # @option opts [object, Array] :args zero or more arguments to be passed + # the task block on execution + # + # @yield The block operation to be performed asynchronously. + # + # @raise [ArgumentError] if no block is given + # + # @see http://wiki.commonjs.org/wiki/Promises/A + # @see http://promises-aplus.github.io/promises-spec/ + def initialize(opts = {}, &block) + opts.delete_if { |k, v| v.nil? } + super(NULL, opts.merge(__promise_body_from_block__: block), &nil) + end + + # Create a new `Promise` and fulfill it immediately. + # + # @!macro executor_and_deref_options + # + # @!macro promise_init_options + # + # @raise [ArgumentError] if no block is given + # + # @return [Promise] the newly created `Promise` + def self.fulfill(value, opts = {}) + Promise.new(opts).tap { |p| p.send(:synchronized_set_state!, true, value, nil) } + end + + # Create a new `Promise` and reject it immediately. + # + # @!macro executor_and_deref_options + # + # @!macro promise_init_options + # + # @raise [ArgumentError] if no block is given + # + # @return [Promise] the newly created `Promise` + def self.reject(reason, opts = {}) + Promise.new(opts).tap { |p| p.send(:synchronized_set_state!, false, nil, reason) } + end + + # Execute an `:unscheduled` `Promise`. Immediately sets the state to `:pending` and + # passes the block to a new thread/thread pool for eventual execution. + # Does nothing if the `Promise` is in any state other than `:unscheduled`. + # + # @return [Promise] a reference to `self` + def execute + if root? + if compare_and_set_state(:pending, :unscheduled) + set_pending + realize(@promise_body) + end + else + compare_and_set_state(:pending, :unscheduled) + @parent.execute + end + self + end + + # @!macro ivar_set_method + # + # @raise [Concurrent::PromiseExecutionError] if not the root promise + def set(value = NULL, &block) + raise PromiseExecutionError.new('supported only on root promise') unless root? + check_for_block_or_value!(block_given?, value) + synchronize do + if @state != :unscheduled + raise MultipleAssignmentError + else + @promise_body = block || Proc.new { |result| value } + end + end + execute + end + + # @!macro ivar_fail_method + # + # @raise [Concurrent::PromiseExecutionError] if not the root promise + def fail(reason = StandardError.new) + set { raise reason } + end + + # Create a new `Promise` object with the given block, execute it, and return the + # `:pending` object. + # + # @!macro executor_and_deref_options + # + # @!macro promise_init_options + # + # @return [Promise] the newly created `Promise` in the `:pending` state + # + # @raise [ArgumentError] if no block is given + # + # @example + # promise = Concurrent::Promise.execute{ sleep(1); 42 } + # promise.state #=> :pending + def self.execute(opts = {}, &block) + new(opts, &block).execute + end + + # Chain a new promise off the current promise. + # + # @return [Promise] the new promise + # @yield The block operation to be performed asynchronously. + # @overload then(rescuer, executor, &block) + # @param [Proc] rescuer An optional rescue block to be executed if the + # promise is rejected. + # @param [ThreadPool] executor An optional thread pool executor to be used + # in the new Promise + # @overload then(rescuer, executor: executor, &block) + # @param [Proc] rescuer An optional rescue block to be executed if the + # promise is rejected. + # @param [ThreadPool] executor An optional thread pool executor to be used + # in the new Promise + def then(*args, &block) + if args.last.is_a?(::Hash) + executor = args.pop[:executor] + rescuer = args.first + else + rescuer, executor = args + end + + executor ||= @executor + + raise ArgumentError.new('rescuers and block are both missing') if rescuer.nil? && !block_given? + block = Proc.new { |result| result } unless block_given? + child = Promise.new( + parent: self, + executor: executor, + on_fulfill: block, + on_reject: rescuer + ) + + synchronize do + child.state = :pending if @state == :pending + child.on_fulfill(apply_deref_options(@value)) if @state == :fulfilled + child.on_reject(@reason) if @state == :rejected + @children << child + end + + child + end + + # Chain onto this promise an action to be undertaken on success + # (fulfillment). + # + # @yield The block to execute + # + # @return [Promise] self + def on_success(&block) + raise ArgumentError.new('no block given') unless block_given? + self.then(&block) + end + + # Chain onto this promise an action to be undertaken on failure + # (rejection). + # + # @yield The block to execute + # + # @return [Promise] self + def rescue(&block) + self.then(block) + end + + alias_method :catch, :rescue + alias_method :on_error, :rescue + + # Yield the successful result to the block that returns a promise. If that + # promise is also successful the result is the result of the yielded promise. + # If either part fails the whole also fails. + # + # @example + # Promise.execute { 1 }.flat_map { |v| Promise.execute { v + 2 } }.value! #=> 3 + # + # @return [Promise] + def flat_map(&block) + child = Promise.new( + parent: self, + executor: ImmediateExecutor.new, + ) + + on_error { |e| child.on_reject(e) } + on_success do |result1| + begin + inner = block.call(result1) + inner.execute + inner.on_success { |result2| child.on_fulfill(result2) } + inner.on_error { |e| child.on_reject(e) } + rescue => e + child.on_reject(e) + end + end + + child + end + + # Builds a promise that produces the result of promises in an Array + # and fails if any of them fails. + # + # @overload zip(*promises) + # @param [Array] promises + # + # @overload zip(*promises, opts) + # @param [Array] promises + # @param [Hash] opts the configuration options + # @option opts [Executor] :executor (ImmediateExecutor.new) when set use the given `Executor` instance. + # @option opts [Boolean] :execute (true) execute promise before returning + # + # @return [Promise] + def self.zip(*promises) + opts = promises.last.is_a?(::Hash) ? promises.pop.dup : {} + opts[:executor] ||= ImmediateExecutor.new + zero = if !opts.key?(:execute) || opts.delete(:execute) + fulfill([], opts) + else + Promise.new(opts) { [] } + end + + promises.reduce(zero) do |p1, p2| + p1.flat_map do |results| + p2.then do |next_result| + results << next_result + end + end + end + end + + # Builds a promise that produces the result of self and others in an Array + # and fails if any of them fails. + # + # @overload zip(*promises) + # @param [Array] others + # + # @overload zip(*promises, opts) + # @param [Array] others + # @param [Hash] opts the configuration options + # @option opts [Executor] :executor (ImmediateExecutor.new) when set use the given `Executor` instance. + # @option opts [Boolean] :execute (true) execute promise before returning + # + # @return [Promise] + def zip(*others) + self.class.zip(self, *others) + end + + # Aggregates a collection of promises and executes the `then` condition + # if all aggregated promises succeed. Executes the `rescue` handler with + # a `Concurrent::PromiseExecutionError` if any of the aggregated promises + # fail. Upon execution will execute any of the aggregate promises that + # were not already executed. + # + # @!macro promise_self_aggregate + # + # The returned promise will not yet have been executed. Additional `#then` + # and `#rescue` handlers may still be provided. Once the returned promise + # is execute the aggregate promises will be also be executed (if they have + # not been executed already). The results of the aggregate promises will + # be checked upon completion. The necessary `#then` and `#rescue` blocks + # on the aggregating promise will then be executed as appropriate. If the + # `#rescue` handlers are executed the raises exception will be + # `Concurrent::PromiseExecutionError`. + # + # @param [Array] promises Zero or more promises to aggregate + # @return [Promise] an unscheduled (not executed) promise that aggregates + # the promises given as arguments + def self.all?(*promises) + aggregate(:all?, *promises) + end + + # Aggregates a collection of promises and executes the `then` condition + # if any aggregated promises succeed. Executes the `rescue` handler with + # a `Concurrent::PromiseExecutionError` if any of the aggregated promises + # fail. Upon execution will execute any of the aggregate promises that + # were not already executed. + # + # @!macro promise_self_aggregate + def self.any?(*promises) + aggregate(:any?, *promises) + end + + protected + + def ns_initialize(value, opts) + super + + @executor = Options.executor_from_options(opts) || Concurrent.global_io_executor + @args = get_arguments_from(opts) + + @parent = opts.fetch(:parent) { nil } + @on_fulfill = opts.fetch(:on_fulfill) { Proc.new { |result| result } } + @on_reject = opts.fetch(:on_reject) { Proc.new { |reason| raise reason } } + + @promise_body = opts[:__promise_body_from_block__] || Proc.new { |result| result } + @state = :unscheduled + @children = [] + end + + # Aggregate a collection of zero or more promises under a composite promise, + # execute the aggregated promises and collect them into a standard Ruby array, + # call the given Ruby `Ennnumerable` predicate (such as `any?`, `all?`, `none?`, + # or `one?`) on the collection checking for the success or failure of each, + # then executing the composite's `#then` handlers if the predicate returns + # `true` or executing the composite's `#rescue` handlers if the predicate + # returns false. + # + # @!macro promise_self_aggregate + def self.aggregate(method, *promises) + composite = Promise.new do + completed = promises.collect do |promise| + promise.execute if promise.unscheduled? + promise.wait + promise + end + unless completed.empty? || completed.send(method){|promise| promise.fulfilled? } + raise PromiseExecutionError + end + end + composite + end + + # @!visibility private + def set_pending + synchronize do + @state = :pending + @children.each { |c| c.set_pending } + end + end + + # @!visibility private + def root? # :nodoc: + @parent.nil? + end + + # @!visibility private + def on_fulfill(result) + realize Proc.new { @on_fulfill.call(result) } + nil + end + + # @!visibility private + def on_reject(reason) + realize Proc.new { @on_reject.call(reason) } + nil + end + + # @!visibility private + def notify_child(child) + if_state(:fulfilled) { child.on_fulfill(apply_deref_options(@value)) } + if_state(:rejected) { child.on_reject(@reason) } + end + + # @!visibility private + def complete(success, value, reason) + children_to_notify = synchronize do + set_state!(success, value, reason) + @children.dup + end + + children_to_notify.each { |child| notify_child(child) } + observers.notify_and_delete_observers{ [Time.now, self.value, reason] } + end + + # @!visibility private + def realize(task) + @executor.post do + success, value, reason = SafeTaskExecutor.new(task, rescue_exception: true).execute(*@args) + complete(success, value, reason) + end + end + + # @!visibility private + def set_state!(success, value, reason) + set_state(success, value, reason) + event.set + end + + # @!visibility private + def synchronized_set_state!(success, value, reason) + synchronize { set_state!(success, value, reason) } + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promises.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promises.rb new file mode 100644 index 0000000000000..c5df8fe9cb9fd --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/promises.rb @@ -0,0 +1,2178 @@ +require 'concurrent/synchronization/object' +require 'concurrent/atomic/atomic_boolean' +require 'concurrent/atomic/atomic_fixnum' +require 'concurrent/collection/lock_free_stack' +require 'concurrent/configuration' +require 'concurrent/errors' +require 'concurrent/re_include' +require 'concurrent/utility/monotonic_time' + +module Concurrent + + # {include:file:docs-source/promises-main.md} + module Promises + + # @!macro promises.param.default_executor + # @param [Executor, :io, :fast] default_executor Instance of an executor or a name of the + # global executor. Default executor propagates to chained futures unless overridden with + # executor parameter or changed with {AbstractEventFuture#with_default_executor}. + # + # @!macro promises.param.executor + # @param [Executor, :io, :fast] executor Instance of an executor or a name of the + # global executor. The task is executed on it, default executor remains unchanged. + # + # @!macro promises.param.args + # @param [Object] args arguments which are passed to the task when it's executed. + # (It might be prepended with other arguments, see the @yield section). + # + # @!macro promises.shortcut.on + # Shortcut of {#$0_on} with default `:io` executor supplied. + # @see #$0_on + # + # @!macro promises.shortcut.using + # Shortcut of {#$0_using} with default `:io` executor supplied. + # @see #$0_using + # + # @!macro promise.param.task-future + # @yieldreturn will become result of the returned Future. + # Its returned value becomes {Future#value} fulfilling it, + # raised exception becomes {Future#reason} rejecting it. + # + # @!macro promise.param.callback + # @yieldreturn is forgotten. + + # Container of all {Future}, {Event} factory methods. They are never constructed directly with + # new. + module FactoryMethods + extend ReInclude + extend self + + module Configuration + # @return [Executor, :io, :fast] the executor which is used when none is supplied + # to a factory method. The method can be overridden in the receivers of + # `include FactoryMethod` + def default_executor + :io + end + end + + include Configuration + + # @!macro promises.shortcut.on + # @return [ResolvableEvent] + def resolvable_event + resolvable_event_on default_executor + end + + # Creates a resolvable event, user is responsible for resolving the event once + # by calling {Promises::ResolvableEvent#resolve}. + # + # @!macro promises.param.default_executor + # @return [ResolvableEvent] + def resolvable_event_on(default_executor = self.default_executor) + ResolvableEventPromise.new(default_executor).future + end + + # @!macro promises.shortcut.on + # @return [ResolvableFuture] + def resolvable_future + resolvable_future_on default_executor + end + + # Creates resolvable future, user is responsible for resolving the future once by + # {Promises::ResolvableFuture#resolve}, {Promises::ResolvableFuture#fulfill}, + # or {Promises::ResolvableFuture#reject} + # + # @!macro promises.param.default_executor + # @return [ResolvableFuture] + def resolvable_future_on(default_executor = self.default_executor) + ResolvableFuturePromise.new(default_executor).future + end + + # @!macro promises.shortcut.on + # @return [Future] + def future(*args, &task) + future_on(default_executor, *args, &task) + end + + # Constructs a new Future which will be resolved after block is evaluated on default executor. + # Evaluation begins immediately. + # + # @!macro promises.param.default_executor + # @!macro promises.param.args + # @yield [*args] to the task. + # @!macro promise.param.task-future + # @return [Future] + def future_on(default_executor, *args, &task) + ImmediateEventPromise.new(default_executor).future.then(*args, &task) + end + + # Creates a resolved future with will be either fulfilled with the given value or rejected with + # the given reason. + # + # @param [true, false] fulfilled + # @param [Object] value + # @param [Object] reason + # @!macro promises.param.default_executor + # @return [Future] + def resolved_future(fulfilled, value, reason, default_executor = self.default_executor) + ImmediateFuturePromise.new(default_executor, fulfilled, value, reason).future + end + + # Creates a resolved future which will be fulfilled with the given value. + # + # @!macro promises.param.default_executor + # @param [Object] value + # @return [Future] + def fulfilled_future(value, default_executor = self.default_executor) + resolved_future true, value, nil, default_executor + end + + # Creates a resolved future which will be rejected with the given reason. + # + # @!macro promises.param.default_executor + # @param [Object] reason + # @return [Future] + def rejected_future(reason, default_executor = self.default_executor) + resolved_future false, nil, reason, default_executor + end + + # Creates resolved event. + # + # @!macro promises.param.default_executor + # @return [Event] + def resolved_event(default_executor = self.default_executor) + ImmediateEventPromise.new(default_executor).event + end + + # General constructor. Behaves differently based on the argument's type. It's provided for convenience + # but it's better to be explicit. + # + # @see rejected_future, resolved_event, fulfilled_future + # @!macro promises.param.default_executor + # @return [Event, Future] + # + # @overload make_future(nil, default_executor = self.default_executor) + # @param [nil] nil + # @return [Event] resolved event. + # + # @overload make_future(a_future, default_executor = self.default_executor) + # @param [Future] a_future + # @return [Future] a future which will be resolved when a_future is. + # + # @overload make_future(an_event, default_executor = self.default_executor) + # @param [Event] an_event + # @return [Event] an event which will be resolved when an_event is. + # + # @overload make_future(exception, default_executor = self.default_executor) + # @param [Exception] exception + # @return [Future] a rejected future with the exception as its reason. + # + # @overload make_future(value, default_executor = self.default_executor) + # @param [Object] value when none of the above overloads fits + # @return [Future] a fulfilled future with the value. + def make_future(argument = nil, default_executor = self.default_executor) + case argument + when AbstractEventFuture + # returning wrapper would change nothing + argument + when Exception + rejected_future argument, default_executor + when nil + resolved_event default_executor + else + fulfilled_future argument, default_executor + end + end + + # @!macro promises.shortcut.on + # @return [Future, Event] + def delay(*args, &task) + delay_on default_executor, *args, &task + end + + # Creates a new event or future which is resolved only after it is touched, + # see {Concurrent::AbstractEventFuture#touch}. + # + # @!macro promises.param.default_executor + # @overload delay_on(default_executor, *args, &task) + # If task is provided it returns a {Future} representing the result of the task. + # @!macro promises.param.args + # @yield [*args] to the task. + # @!macro promise.param.task-future + # @return [Future] + # @overload delay_on(default_executor) + # If no task is provided, it returns an {Event} + # @return [Event] + def delay_on(default_executor, *args, &task) + event = DelayPromise.new(default_executor).event + task ? event.chain(*args, &task) : event + end + + # @!macro promises.shortcut.on + # @return [Future, Event] + def schedule(intended_time, *args, &task) + schedule_on default_executor, intended_time, *args, &task + end + + # Creates a new event or future which is resolved in intended_time. + # + # @!macro promises.param.default_executor + # @!macro promises.param.intended_time + # @param [Numeric, Time] intended_time `Numeric` means to run in `intended_time` seconds. + # `Time` means to run on `intended_time`. + # @overload schedule_on(default_executor, intended_time, *args, &task) + # If task is provided it returns a {Future} representing the result of the task. + # @!macro promises.param.args + # @yield [*args] to the task. + # @!macro promise.param.task-future + # @return [Future] + # @overload schedule_on(default_executor, intended_time) + # If no task is provided, it returns an {Event} + # @return [Event] + def schedule_on(default_executor, intended_time, *args, &task) + event = ScheduledPromise.new(default_executor, intended_time).event + task ? event.chain(*args, &task) : event + end + + # @!macro promises.shortcut.on + # @return [Future] + def zip_futures(*futures_and_or_events) + zip_futures_on default_executor, *futures_and_or_events + end + + # Creates a new future which is resolved after all futures_and_or_events are resolved. + # Its value is an array of zipped future values. Its reason is an array of reasons for rejection. + # If there is an error it rejects. + # @!macro promises.event-conversion + # If event is supplied, which does not have value and can be only resolved, it's + # represented as `:fulfilled` with value `nil`. + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Future] + def zip_futures_on(default_executor, *futures_and_or_events) + ZipFuturesPromise.new_blocked_by(futures_and_or_events, default_executor).future + end + + alias_method :zip, :zip_futures + + # @!macro promises.shortcut.on + # @return [Event] + def zip_events(*futures_and_or_events) + zip_events_on default_executor, *futures_and_or_events + end + + # Creates a new event which is resolved after all futures_and_or_events are resolved. + # (Future is resolved when fulfilled or rejected.) + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Event] + def zip_events_on(default_executor, *futures_and_or_events) + ZipEventsPromise.new_blocked_by(futures_and_or_events, default_executor).event + end + + # @!macro promises.shortcut.on + # @return [Future] + def any_resolved_future(*futures_and_or_events) + any_resolved_future_on default_executor, *futures_and_or_events + end + + alias_method :any, :any_resolved_future + + # Creates a new future which is resolved after the first futures_and_or_events is resolved. + # Its result equals the result of the first resolved future. + # @!macro promises.any-touch + # If resolved it does not propagate {Concurrent::AbstractEventFuture#touch}, leaving delayed + # futures un-executed if they are not required any more. + # @!macro promises.event-conversion + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Future] + def any_resolved_future_on(default_executor, *futures_and_or_events) + AnyResolvedFuturePromise.new_blocked_by(futures_and_or_events, default_executor).future + end + + # @!macro promises.shortcut.on + # @return [Future] + def any_fulfilled_future(*futures_and_or_events) + any_fulfilled_future_on default_executor, *futures_and_or_events + end + + # Creates a new future which is resolved after the first futures_and_or_events is fulfilled. + # Its result equals the result of the first resolved future or if all futures_and_or_events reject, + # it has reason of the last rejected future. + # @!macro promises.any-touch + # @!macro promises.event-conversion + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Future] + def any_fulfilled_future_on(default_executor, *futures_and_or_events) + AnyFulfilledFuturePromise.new_blocked_by(futures_and_or_events, default_executor).future + end + + # @!macro promises.shortcut.on + # @return [Event] + def any_event(*futures_and_or_events) + any_event_on default_executor, *futures_and_or_events + end + + # Creates a new event which becomes resolved after the first futures_and_or_events resolves. + # @!macro promises.any-touch + # + # @!macro promises.param.default_executor + # @param [AbstractEventFuture] futures_and_or_events + # @return [Event] + def any_event_on(default_executor, *futures_and_or_events) + AnyResolvedEventPromise.new_blocked_by(futures_and_or_events, default_executor).event + end + + # TODO consider adding first(count, *futures) + # TODO consider adding zip_by(slice, *futures) processing futures in slices + # TODO or rather a generic aggregator taking a function + end + + module InternalStates + # @!visibility private + class State + def resolved? + raise NotImplementedError + end + + def to_sym + raise NotImplementedError + end + end + + # @!visibility private + class Pending < State + def resolved? + false + end + + def to_sym + :pending + end + end + + # @!visibility private + class Reserved < Pending + end + + # @!visibility private + class ResolvedWithResult < State + def resolved? + true + end + + def to_sym + :resolved + end + + def result + [fulfilled?, value, reason] + end + + def fulfilled? + raise NotImplementedError + end + + def value + raise NotImplementedError + end + + def reason + raise NotImplementedError + end + + def apply + raise NotImplementedError + end + end + + # @!visibility private + class Fulfilled < ResolvedWithResult + + def initialize(value) + @Value = value + end + + def fulfilled? + true + end + + def apply(args, block) + block.call value, *args + end + + def value + @Value + end + + def reason + nil + end + + def to_sym + :fulfilled + end + end + + # @!visibility private + class FulfilledArray < Fulfilled + def apply(args, block) + block.call(*value, *args) + end + end + + # @!visibility private + class Rejected < ResolvedWithResult + def initialize(reason) + @Reason = reason + end + + def fulfilled? + false + end + + def value + nil + end + + def reason + @Reason + end + + def to_sym + :rejected + end + + def apply(args, block) + block.call reason, *args + end + end + + # @!visibility private + class PartiallyRejected < ResolvedWithResult + def initialize(value, reason) + super() + @Value = value + @Reason = reason + end + + def fulfilled? + false + end + + def to_sym + :rejected + end + + def value + @Value + end + + def reason + @Reason + end + + def apply(args, block) + block.call(*reason, *args) + end + end + + # @!visibility private + PENDING = Pending.new + # @!visibility private + RESERVED = Reserved.new + # @!visibility private + RESOLVED = Fulfilled.new(nil) + + def RESOLVED.to_sym + :resolved + end + end + + private_constant :InternalStates + + # @!macro promises.shortcut.event-future + # @see Event#$0 + # @see Future#$0 + + # @!macro promises.param.timeout + # @param [Numeric] timeout the maximum time in second to wait. + + # @!macro promises.warn.blocks + # @note This function potentially blocks current thread until the Future is resolved. + # Be careful it can deadlock. Try to chain instead. + + # Common ancestor of {Event} and {Future} classes, many shared methods are defined here. + class AbstractEventFuture < Synchronization::Object + safe_initialization! + attr_atomic(:internal_state) + private :internal_state=, :swap_internal_state, :compare_and_set_internal_state, :update_internal_state + # @!method internal_state + # @!visibility private + + include InternalStates + + def initialize(promise, default_executor) + super() + @Lock = Mutex.new + @Condition = ConditionVariable.new + @Promise = promise + @DefaultExecutor = default_executor + @Callbacks = LockFreeStack.new + @Waiters = AtomicFixnum.new 0 + self.internal_state = PENDING + end + + private :initialize + + # Returns its state. + # @return [Symbol] + # + # @overload an_event.state + # @return [:pending, :resolved] + # @overload a_future.state + # Both :fulfilled, :rejected implies :resolved. + # @return [:pending, :fulfilled, :rejected] + def state + internal_state.to_sym + end + + # Is it in pending state? + # @return [Boolean] + def pending? + !internal_state.resolved? + end + + # Is it in resolved state? + # @return [Boolean] + def resolved? + internal_state.resolved? + end + + # Propagates touch. Requests all the delayed futures, which it depends on, to be + # executed. This method is called by any other method requiring resolved state, like {#wait}. + # @return [self] + def touch + @Promise.touch + self + end + + # @!macro promises.touches + # Calls {Concurrent::AbstractEventFuture#touch}. + + # @!macro promises.method.wait + # Wait (block the Thread) until receiver is {#resolved?}. + # @!macro promises.touches + # + # @!macro promises.warn.blocks + # @!macro promises.param.timeout + # @return [self, true, false] self implies timeout was not used, true implies timeout was used + # and it was resolved, false implies it was not resolved within timeout. + def wait(timeout = nil) + result = wait_until_resolved(timeout) + timeout ? result : self + end + + # Returns default executor. + # @return [Executor] default executor + # @see #with_default_executor + # @see FactoryMethods#future_on + # @see FactoryMethods#resolvable_future + # @see FactoryMethods#any_fulfilled_future_on + # @see similar + def default_executor + @DefaultExecutor + end + + # @!macro promises.shortcut.on + # @return [Future] + def chain(*args, &task) + chain_on @DefaultExecutor, *args, &task + end + + # Chains the task to be executed asynchronously on executor after it is resolved. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @return [Future] + # @!macro promise.param.task-future + # + # @overload an_event.chain_on(executor, *args, &task) + # @yield [*args] to the task. + # @overload a_future.chain_on(executor, *args, &task) + # @yield [fulfilled, value, reason, *args] to the task. + # @yieldparam [true, false] fulfilled + # @yieldparam [Object] value + # @yieldparam [Object] reason + def chain_on(executor, *args, &task) + ChainPromise.new_blocked_by1(self, executor, executor, args, &task).future + end + + # @return [String] Short string representation. + def to_s + format '%s %s>', super[0..-2], state + end + + alias_method :inspect, :to_s + + # Resolves the resolvable when receiver is resolved. + # + # @param [Resolvable] resolvable + # @return [self] + def chain_resolvable(resolvable) + on_resolution! { resolvable.resolve_with internal_state } + end + + alias_method :tangle, :chain_resolvable + + # @!macro promises.shortcut.using + # @return [self] + def on_resolution(*args, &callback) + on_resolution_using @DefaultExecutor, *args, &callback + end + + # Stores the callback to be executed synchronously on resolving thread after it is + # resolved. + # + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # + # @overload an_event.on_resolution!(*args, &callback) + # @yield [*args] to the callback. + # @overload a_future.on_resolution!(*args, &callback) + # @yield [fulfilled, value, reason, *args] to the callback. + # @yieldparam [true, false] fulfilled + # @yieldparam [Object] value + # @yieldparam [Object] reason + def on_resolution!(*args, &callback) + add_callback :callback_on_resolution, args, callback + end + + # Stores the callback to be executed asynchronously on executor after it is resolved. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # + # @overload an_event.on_resolution_using(executor, *args, &callback) + # @yield [*args] to the callback. + # @overload a_future.on_resolution_using(executor, *args, &callback) + # @yield [fulfilled, value, reason, *args] to the callback. + # @yieldparam [true, false] fulfilled + # @yieldparam [Object] value + # @yieldparam [Object] reason + def on_resolution_using(executor, *args, &callback) + add_callback :async_callback_on_resolution, executor, args, callback + end + + # @!macro promises.method.with_default_executor + # Crates new object with same class with the executor set as its new default executor. + # Any futures depending on it will use the new default executor. + # @!macro promises.shortcut.event-future + # @abstract + # @return [AbstractEventFuture] + def with_default_executor(executor) + raise NotImplementedError + end + + # @!visibility private + def resolve_with(state, raise_on_reassign = true, reserved = false) + if compare_and_set_internal_state(reserved ? RESERVED : PENDING, state) + # go to synchronized block only if there were waiting threads + @Lock.synchronize { @Condition.broadcast } unless @Waiters.value == 0 + call_callbacks state + else + return rejected_resolution(raise_on_reassign, state) + end + self + end + + # For inspection. + # @!visibility private + # @return [Array] + def blocks + @Callbacks.each_with_object([]) do |(method, args), promises| + promises.push(args[0]) if method == :callback_notify_blocked + end + end + + # For inspection. + # @!visibility private + def callbacks + @Callbacks.each.to_a + end + + # For inspection. + # @!visibility private + def promise + @Promise + end + + # For inspection. + # @!visibility private + def touched? + promise.touched? + end + + # For inspection. + # @!visibility private + def waiting_threads + @Waiters.each.to_a + end + + # @!visibility private + def add_callback_notify_blocked(promise, index) + add_callback :callback_notify_blocked, promise, index + end + + # @!visibility private + def add_callback_clear_delayed_node(node) + add_callback(:callback_clear_delayed_node, node) + end + + # @!visibility private + def with_hidden_resolvable + # TODO (pitr-ch 10-Dec-2018): documentation, better name if in edge + self + end + + private + + def add_callback(method, *args) + state = internal_state + if state.resolved? + call_callback method, state, args + else + @Callbacks.push [method, args] + state = internal_state + # take back if it was resolved in the meanwhile + call_callbacks state if state.resolved? + end + self + end + + def callback_clear_delayed_node(state, node) + node.value = nil + end + + # @return [Boolean] + def wait_until_resolved(timeout) + return true if resolved? + + touch + + @Lock.synchronize do + @Waiters.increment + begin + if timeout + start = Concurrent.monotonic_time + until resolved? + break if @Condition.wait(@Lock, timeout) == nil # nil means timeout + timeout -= (Concurrent.monotonic_time - start) + break if timeout <= 0 + end + else + until resolved? + @Condition.wait(@Lock, timeout) + end + end + ensure + # JRuby may raise ConcurrencyError + @Waiters.decrement + end + end + resolved? + end + + def call_callback(method, state, args) + self.send method, state, *args + end + + def call_callbacks(state) + method, args = @Callbacks.pop + while method + call_callback method, state, args + method, args = @Callbacks.pop + end + end + + def with_async(executor, *args, &block) + Concurrent.executor(executor).post(*args, &block) + end + + def async_callback_on_resolution(state, executor, args, callback) + with_async(executor, state, args, callback) do |st, ar, cb| + callback_on_resolution st, ar, cb + end + end + + def callback_notify_blocked(state, promise, index) + promise.on_blocker_resolution self, index + end + end + + # Represents an event which will happen in future (will be resolved). The event is either + # pending or resolved. It should be always resolved. Use {Future} to communicate rejections and + # cancellation. + class Event < AbstractEventFuture + + alias_method :then, :chain + + + # @!macro promises.method.zip + # Creates a new event or a future which will be resolved when receiver and other are. + # Returns an event if receiver and other are events, otherwise returns a future. + # If just one of the parties is Future then the result + # of the returned future is equal to the result of the supplied future. If both are futures + # then the result is as described in {FactoryMethods#zip_futures_on}. + # + # @return [Future, Event] + def zip(other) + if other.is_a?(Future) + ZipFutureEventPromise.new_blocked_by2(other, self, @DefaultExecutor).future + else + ZipEventEventPromise.new_blocked_by2(self, other, @DefaultExecutor).event + end + end + + alias_method :&, :zip + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. + # + # @return [Event] + def any(event_or_future) + AnyResolvedEventPromise.new_blocked_by2(self, event_or_future, @DefaultExecutor).event + end + + alias_method :|, :any + + # Creates new event dependent on receiver which will not evaluate until touched, see {#touch}. + # In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated. + # + # @return [Event] + def delay + event = DelayPromise.new(@DefaultExecutor).event + ZipEventEventPromise.new_blocked_by2(self, event, @DefaultExecutor).event + end + + # @!macro promise.method.schedule + # Creates new event dependent on receiver scheduled to execute on/in intended_time. + # In time is interpreted from the moment the receiver is resolved, therefore it inserts + # delay into the chain. + # + # @!macro promises.param.intended_time + # @return [Event] + def schedule(intended_time) + chain do + event = ScheduledPromise.new(@DefaultExecutor, intended_time).event + ZipEventEventPromise.new_blocked_by2(self, event, @DefaultExecutor).event + end.flat_event + end + + # Converts event to a future. The future is fulfilled when the event is resolved, the future may never fail. + # + # @return [Future] + def to_future + future = Promises.resolvable_future + ensure + chain_resolvable(future) + end + + # Returns self, since this is event + # @return [Event] + def to_event + self + end + + # @!macro promises.method.with_default_executor + # @return [Event] + def with_default_executor(executor) + EventWrapperPromise.new_blocked_by1(self, executor).event + end + + private + + def rejected_resolution(raise_on_reassign, state) + raise Concurrent::MultipleAssignmentError.new('Event can be resolved only once') if raise_on_reassign + return false + end + + def callback_on_resolution(state, args, callback) + callback.call(*args) + end + end + + # Represents a value which will become available in future. May reject with a reason instead, + # e.g. when the tasks raises an exception. + class Future < AbstractEventFuture + + # Is it in fulfilled state? + # @return [Boolean] + def fulfilled? + state = internal_state + state.resolved? && state.fulfilled? + end + + # Is it in rejected state? + # @return [Boolean] + def rejected? + state = internal_state + state.resolved? && !state.fulfilled? + end + + # @!macro promises.warn.nil + # @note Make sure returned `nil` is not confused with timeout, no value when rejected, + # no reason when fulfilled, etc. + # Use more exact methods if needed, like {#wait}, {#value!}, {#result}, etc. + + # @!macro promises.method.value + # Return value of the future. + # @!macro promises.touches + # + # @!macro promises.warn.blocks + # @!macro promises.warn.nil + # @!macro promises.param.timeout + # @!macro promises.param.timeout_value + # @param [Object] timeout_value a value returned by the method when it times out + # @return [Object, nil, timeout_value] the value of the Future when fulfilled, + # timeout_value on timeout, + # nil on rejection. + def value(timeout = nil, timeout_value = nil) + if wait_until_resolved timeout + internal_state.value + else + timeout_value + end + end + + # Returns reason of future's rejection. + # @!macro promises.touches + # + # @!macro promises.warn.blocks + # @!macro promises.warn.nil + # @!macro promises.param.timeout + # @!macro promises.param.timeout_value + # @return [Object, timeout_value] the reason, or timeout_value on timeout, or nil on fulfillment. + def reason(timeout = nil, timeout_value = nil) + if wait_until_resolved timeout + internal_state.reason + else + timeout_value + end + end + + # Returns triplet fulfilled?, value, reason. + # @!macro promises.touches + # + # @!macro promises.warn.blocks + # @!macro promises.param.timeout + # @return [Array(Boolean, Object, Object), nil] triplet of fulfilled?, value, reason, or nil + # on timeout. + def result(timeout = nil) + internal_state.result if wait_until_resolved timeout + end + + # @!macro promises.method.wait + # @raise [Exception] {#reason} on rejection + def wait!(timeout = nil) + result = wait_until_resolved!(timeout) + timeout ? result : self + end + + # @!macro promises.method.value + # @return [Object, nil, timeout_value] the value of the Future when fulfilled, + # or nil on rejection, + # or timeout_value on timeout. + # @raise [Exception] {#reason} on rejection + def value!(timeout = nil, timeout_value = nil) + if wait_until_resolved! timeout + internal_state.value + else + timeout_value + end + end + + # Allows rejected Future to be risen with `raise` method. + # If the reason is not an exception `Runtime.new(reason)` is returned. + # + # @example + # raise Promises.rejected_future(StandardError.new("boom")) + # raise Promises.rejected_future("or just boom") + # @raise [Concurrent::Error] when raising not rejected future + # @return [Exception] + def exception(*args) + raise Concurrent::Error, 'it is not rejected' unless rejected? + raise ArgumentError unless args.size <= 1 + reason = Array(internal_state.reason).flatten.compact + if reason.size > 1 + ex = Concurrent::MultipleErrors.new reason + ex.set_backtrace(caller) + ex + else + ex = if reason[0].respond_to? :exception + reason[0].exception(*args) + else + RuntimeError.new(reason[0]).exception(*args) + end + ex.set_backtrace Array(ex.backtrace) + caller + ex + end + end + + # @!macro promises.shortcut.on + # @return [Future] + def then(*args, &task) + then_on @DefaultExecutor, *args, &task + end + + # Chains the task to be executed asynchronously on executor after it fulfills. Does not run + # the task if it rejects. It will resolve though, triggering any dependent futures. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.task-future + # @return [Future] + # @yield [value, *args] to the task. + def then_on(executor, *args, &task) + ThenPromise.new_blocked_by1(self, executor, executor, args, &task).future + end + + # @!macro promises.shortcut.on + # @return [Future] + def rescue(*args, &task) + rescue_on @DefaultExecutor, *args, &task + end + + # Chains the task to be executed asynchronously on executor after it rejects. Does not run + # the task if it fulfills. It will resolve though, triggering any dependent futures. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.task-future + # @return [Future] + # @yield [reason, *args] to the task. + def rescue_on(executor, *args, &task) + RescuePromise.new_blocked_by1(self, executor, executor, args, &task).future + end + + # @!macro promises.method.zip + # @return [Future] + def zip(other) + if other.is_a?(Future) + ZipFuturesPromise.new_blocked_by2(self, other, @DefaultExecutor).future + else + ZipFutureEventPromise.new_blocked_by2(self, other, @DefaultExecutor).future + end + end + + alias_method :&, :zip + + # Creates a new event which will be resolved when the first of receiver, `event_or_future` + # resolves. Returning future will have value nil if event_or_future is event and resolves + # first. + # + # @return [Future] + def any(event_or_future) + AnyResolvedFuturePromise.new_blocked_by2(self, event_or_future, @DefaultExecutor).future + end + + alias_method :|, :any + + # Creates new future dependent on receiver which will not evaluate until touched, see {#touch}. + # In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated. + # + # @return [Future] + def delay + event = DelayPromise.new(@DefaultExecutor).event + ZipFutureEventPromise.new_blocked_by2(self, event, @DefaultExecutor).future + end + + # @!macro promise.method.schedule + # @return [Future] + def schedule(intended_time) + chain do + event = ScheduledPromise.new(@DefaultExecutor, intended_time).event + ZipFutureEventPromise.new_blocked_by2(self, event, @DefaultExecutor).future + end.flat + end + + # @!macro promises.method.with_default_executor + # @return [Future] + def with_default_executor(executor) + FutureWrapperPromise.new_blocked_by1(self, executor).future + end + + # Creates new future which will have result of the future returned by receiver. If receiver + # rejects it will have its rejection. + # + # @param [Integer] level how many levels of futures should flatten + # @return [Future] + def flat_future(level = 1) + FlatFuturePromise.new_blocked_by1(self, level, @DefaultExecutor).future + end + + alias_method :flat, :flat_future + + # Creates new event which will be resolved when the returned event by receiver is. + # Be careful if the receiver rejects it will just resolve since Event does not hold reason. + # + # @return [Event] + def flat_event + FlatEventPromise.new_blocked_by1(self, @DefaultExecutor).event + end + + # @!macro promises.shortcut.using + # @return [self] + def on_fulfillment(*args, &callback) + on_fulfillment_using @DefaultExecutor, *args, &callback + end + + # Stores the callback to be executed synchronously on resolving thread after it is + # fulfilled. Does nothing on rejection. + # + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # @yield [value, *args] to the callback. + def on_fulfillment!(*args, &callback) + add_callback :callback_on_fulfillment, args, callback + end + + # Stores the callback to be executed asynchronously on executor after it is + # fulfilled. Does nothing on rejection. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # @yield [value, *args] to the callback. + def on_fulfillment_using(executor, *args, &callback) + add_callback :async_callback_on_fulfillment, executor, args, callback + end + + # @!macro promises.shortcut.using + # @return [self] + def on_rejection(*args, &callback) + on_rejection_using @DefaultExecutor, *args, &callback + end + + # Stores the callback to be executed synchronously on resolving thread after it is + # rejected. Does nothing on fulfillment. + # + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # @yield [reason, *args] to the callback. + def on_rejection!(*args, &callback) + add_callback :callback_on_rejection, args, callback + end + + # Stores the callback to be executed asynchronously on executor after it is + # rejected. Does nothing on fulfillment. + # + # @!macro promises.param.executor + # @!macro promises.param.args + # @!macro promise.param.callback + # @return [self] + # @yield [reason, *args] to the callback. + def on_rejection_using(executor, *args, &callback) + add_callback :async_callback_on_rejection, executor, args, callback + end + + # Allows to use futures as green threads. The receiver has to evaluate to a future which + # represents what should be done next. It basically flattens indefinitely until non Future + # values is returned which becomes result of the returned future. Any encountered exception + # will become reason of the returned future. + # + # @return [Future] + # @param [#call(value)] run_test + # an object which when called returns either Future to keep running with + # or nil, then the run completes with the value. + # The run_test can be used to extract the Future from deeper structure, + # or to distinguish Future which is a resulting value from a future + # which is suppose to continue running. + # @example + # body = lambda do |v| + # v += 1 + # v < 5 ? Promises.future(v, &body) : v + # end + # Promises.future(0, &body).run.value! # => 5 + def run(run_test = method(:run_test)) + RunFuturePromise.new_blocked_by1(self, @DefaultExecutor, run_test).future + end + + # @!visibility private + def apply(args, block) + internal_state.apply args, block + end + + # Converts future to event which is resolved when future is resolved by fulfillment or rejection. + # + # @return [Event] + def to_event + event = Promises.resolvable_event + ensure + chain_resolvable(event) + end + + # Returns self, since this is a future + # @return [Future] + def to_future + self + end + + # @return [String] Short string representation. + def to_s + if resolved? + format '%s with %s>', super[0..-2], (fulfilled? ? value : reason).inspect + else + super + end + end + + alias_method :inspect, :to_s + + private + + def run_test(v) + v if v.is_a?(Future) + end + + def rejected_resolution(raise_on_reassign, state) + if raise_on_reassign + if internal_state == RESERVED + raise Concurrent::MultipleAssignmentError.new( + "Future can be resolved only once. It is already reserved.") + else + raise Concurrent::MultipleAssignmentError.new( + "Future can be resolved only once. It's #{result}, trying to set #{state.result}.", + current_result: result, + new_result: state.result) + end + end + return false + end + + def wait_until_resolved!(timeout = nil) + result = wait_until_resolved(timeout) + raise self if rejected? + result + end + + def async_callback_on_fulfillment(state, executor, args, callback) + with_async(executor, state, args, callback) do |st, ar, cb| + callback_on_fulfillment st, ar, cb + end + end + + def async_callback_on_rejection(state, executor, args, callback) + with_async(executor, state, args, callback) do |st, ar, cb| + callback_on_rejection st, ar, cb + end + end + + def callback_on_fulfillment(state, args, callback) + state.apply args, callback if state.fulfilled? + end + + def callback_on_rejection(state, args, callback) + state.apply args, callback unless state.fulfilled? + end + + def callback_on_resolution(state, args, callback) + callback.call(*state.result, *args) + end + + end + + # Marker module of Future, Event resolved manually. + module Resolvable + include InternalStates + end + + # A Event which can be resolved by user. + class ResolvableEvent < Event + include Resolvable + + # @!macro raise_on_reassign + # @raise [MultipleAssignmentError] when already resolved and raise_on_reassign is true. + + # @!macro promise.param.raise_on_reassign + # @param [Boolean] raise_on_reassign should method raise exception if already resolved + # @return [self, false] false is returned when raise_on_reassign is false and the receiver + # is already resolved. + # + + # Makes the event resolved, which triggers all dependent futures. + # + # @!macro promise.param.raise_on_reassign + # @!macro promise.param.reserved + # @param [true, false] reserved + # Set to true if the resolvable is {#reserve}d by you, + # marks resolution of reserved resolvable events and futures explicitly. + # Advanced feature, ignore unless you use {Resolvable#reserve} from edge. + def resolve(raise_on_reassign = true, reserved = false) + resolve_with RESOLVED, raise_on_reassign, reserved + end + + # Creates new event wrapping receiver, effectively hiding the resolve method. + # + # @return [Event] + def with_hidden_resolvable + @with_hidden_resolvable ||= EventWrapperPromise.new_blocked_by1(self, @DefaultExecutor).event + end + + # Behaves as {AbstractEventFuture#wait} but has one additional optional argument + # resolve_on_timeout. + # + # @param [true, false] resolve_on_timeout + # If it times out and the argument is true it will also resolve the event. + # @return [self, true, false] + # @see AbstractEventFuture#wait + def wait(timeout = nil, resolve_on_timeout = false) + super(timeout) or if resolve_on_timeout + # if it fails to resolve it was resolved in the meantime + # so return true as if there was no timeout + !resolve(false) + else + false + end + end + end + + # A Future which can be resolved by user. + class ResolvableFuture < Future + include Resolvable + + # Makes the future resolved with result of triplet `fulfilled?`, `value`, `reason`, + # which triggers all dependent futures. + # + # @param [true, false] fulfilled + # @param [Object] value + # @param [Object] reason + # @!macro promise.param.raise_on_reassign + # @!macro promise.param.reserved + def resolve(fulfilled = true, value = nil, reason = nil, raise_on_reassign = true, reserved = false) + resolve_with(fulfilled ? Fulfilled.new(value) : Rejected.new(reason), raise_on_reassign, reserved) + end + + # Makes the future fulfilled with `value`, + # which triggers all dependent futures. + # + # @param [Object] value + # @!macro promise.param.raise_on_reassign + # @!macro promise.param.reserved + def fulfill(value, raise_on_reassign = true, reserved = false) + resolve_with Fulfilled.new(value), raise_on_reassign, reserved + end + + # Makes the future rejected with `reason`, + # which triggers all dependent futures. + # + # @param [Object] reason + # @!macro promise.param.raise_on_reassign + # @!macro promise.param.reserved + def reject(reason, raise_on_reassign = true, reserved = false) + resolve_with Rejected.new(reason), raise_on_reassign, reserved + end + + # Evaluates the block and sets its result as future's value fulfilling, if the block raises + # an exception the future rejects with it. + # + # @yield [*args] to the block. + # @yieldreturn [Object] value + # @return [self] + def evaluate_to(*args, &block) + promise.evaluate_to(*args, block) + end + + # Evaluates the block and sets its result as future's value fulfilling, if the block raises + # an exception the future rejects with it. + # + # @yield [*args] to the block. + # @yieldreturn [Object] value + # @return [self] + # @raise [Exception] also raise reason on rejection. + def evaluate_to!(*args, &block) + promise.evaluate_to(*args, block).wait! + end + + # @!macro promises.resolvable.resolve_on_timeout + # @param [::Array(true, Object, nil), ::Array(false, nil, Exception), nil] resolve_on_timeout + # If it times out and the argument is not nil it will also resolve the future + # to the provided resolution. + + # Behaves as {AbstractEventFuture#wait} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [self, true, false] + # @see AbstractEventFuture#wait + def wait(timeout = nil, resolve_on_timeout = nil) + super(timeout) or if resolve_on_timeout + # if it fails to resolve it was resolved in the meantime + # so return true as if there was no timeout + !resolve(*resolve_on_timeout, false) + else + false + end + end + + # Behaves as {Future#wait!} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [self, true, false] + # @raise [Exception] {#reason} on rejection + # @see Future#wait! + def wait!(timeout = nil, resolve_on_timeout = nil) + super(timeout) or if resolve_on_timeout + if resolve(*resolve_on_timeout, false) + false + else + # if it fails to resolve it was resolved in the meantime + # so return true as if there was no timeout + raise self if rejected? + true + end + else + false + end + end + + # Behaves as {Future#value} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [Object, timeout_value, nil] + # @see Future#value + def value(timeout = nil, timeout_value = nil, resolve_on_timeout = nil) + if wait_until_resolved timeout + internal_state.value + else + if resolve_on_timeout + unless resolve(*resolve_on_timeout, false) + # if it fails to resolve it was resolved in the meantime + # so return value as if there was no timeout + return internal_state.value + end + end + timeout_value + end + end + + # Behaves as {Future#value!} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [Object, timeout_value, nil] + # @raise [Exception] {#reason} on rejection + # @see Future#value! + def value!(timeout = nil, timeout_value = nil, resolve_on_timeout = nil) + if wait_until_resolved! timeout + internal_state.value + else + if resolve_on_timeout + unless resolve(*resolve_on_timeout, false) + # if it fails to resolve it was resolved in the meantime + # so return value as if there was no timeout + raise self if rejected? + return internal_state.value + end + end + timeout_value + end + end + + # Behaves as {Future#reason} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [Exception, timeout_value, nil] + # @see Future#reason + def reason(timeout = nil, timeout_value = nil, resolve_on_timeout = nil) + if wait_until_resolved timeout + internal_state.reason + else + if resolve_on_timeout + unless resolve(*resolve_on_timeout, false) + # if it fails to resolve it was resolved in the meantime + # so return value as if there was no timeout + return internal_state.reason + end + end + timeout_value + end + end + + # Behaves as {Future#result} but has one additional optional argument + # resolve_on_timeout. + # + # @!macro promises.resolvable.resolve_on_timeout + # @return [::Array(Boolean, Object, Exception), nil] + # @see Future#result + def result(timeout = nil, resolve_on_timeout = nil) + if wait_until_resolved timeout + internal_state.result + else + if resolve_on_timeout + unless resolve(*resolve_on_timeout, false) + # if it fails to resolve it was resolved in the meantime + # so return value as if there was no timeout + internal_state.result + end + end + # otherwise returns nil + end + end + + # Creates new future wrapping receiver, effectively hiding the resolve method and similar. + # + # @return [Future] + def with_hidden_resolvable + @with_hidden_resolvable ||= FutureWrapperPromise.new_blocked_by1(self, @DefaultExecutor).future + end + end + + # @abstract + # @private + class AbstractPromise < Synchronization::Object + safe_initialization! + include InternalStates + + def initialize(future) + super() + @Future = future + end + + def future + @Future + end + + alias_method :event, :future + + def default_executor + future.default_executor + end + + def state + future.state + end + + def touch + end + + def to_s + format '%s %s>', super[0..-2], @Future + end + + alias_method :inspect, :to_s + + def delayed_because + nil + end + + private + + def resolve_with(new_state, raise_on_reassign = true) + @Future.resolve_with(new_state, raise_on_reassign) + end + + # @return [Future] + def evaluate_to(*args, block) + resolve_with Fulfilled.new(block.call(*args)) + rescue Exception => error + resolve_with Rejected.new(error) + raise error unless error.is_a?(StandardError) + end + end + + class ResolvableEventPromise < AbstractPromise + def initialize(default_executor) + super ResolvableEvent.new(self, default_executor) + end + end + + class ResolvableFuturePromise < AbstractPromise + def initialize(default_executor) + super ResolvableFuture.new(self, default_executor) + end + + public :evaluate_to + end + + # @abstract + class InnerPromise < AbstractPromise + end + + # @abstract + class BlockedPromise < InnerPromise + + private_class_method :new + + def self.new_blocked_by1(blocker, *args, &block) + blocker_delayed = blocker.promise.delayed_because + promise = new(blocker_delayed, 1, *args, &block) + blocker.add_callback_notify_blocked promise, 0 + promise + end + + def self.new_blocked_by2(blocker1, blocker2, *args, &block) + blocker_delayed1 = blocker1.promise.delayed_because + blocker_delayed2 = blocker2.promise.delayed_because + delayed = if blocker_delayed1 && blocker_delayed2 + # TODO (pitr-ch 23-Dec-2016): use arrays when we know it will not grow (only flat adds delay) + LockFreeStack.of2(blocker_delayed1, blocker_delayed2) + else + blocker_delayed1 || blocker_delayed2 + end + promise = new(delayed, 2, *args, &block) + blocker1.add_callback_notify_blocked promise, 0 + blocker2.add_callback_notify_blocked promise, 1 + promise + end + + def self.new_blocked_by(blockers, *args, &block) + delayed = blockers.reduce(nil) { |d, f| add_delayed d, f.promise.delayed_because } + promise = new(delayed, blockers.size, *args, &block) + blockers.each_with_index { |f, i| f.add_callback_notify_blocked promise, i } + promise + end + + def self.add_delayed(delayed1, delayed2) + if delayed1 && delayed2 + delayed1.push delayed2 + delayed1 + else + delayed1 || delayed2 + end + end + + def initialize(delayed, blockers_count, future) + super(future) + @Delayed = delayed + @Countdown = AtomicFixnum.new blockers_count + end + + def on_blocker_resolution(future, index) + countdown = process_on_blocker_resolution(future, index) + resolvable = resolvable?(countdown, future, index) + + on_resolvable(future, index) if resolvable + end + + def delayed_because + @Delayed + end + + def touch + clear_and_propagate_touch + end + + # for inspection only + def blocked_by + blocked_by = [] + ObjectSpace.each_object(AbstractEventFuture) { |o| blocked_by.push o if o.blocks.include? self } + blocked_by + end + + private + + def clear_and_propagate_touch(stack_or_element = @Delayed) + return if stack_or_element.nil? + + if stack_or_element.is_a? LockFreeStack + stack_or_element.clear_each { |element| clear_and_propagate_touch element } + else + stack_or_element.touch unless stack_or_element.nil? # if still present + end + end + + # @return [true,false] if resolvable + def resolvable?(countdown, future, index) + countdown.zero? + end + + def process_on_blocker_resolution(future, index) + @Countdown.decrement + end + + def on_resolvable(resolved_future, index) + raise NotImplementedError + end + end + + # @abstract + class BlockedTaskPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor, executor, args, &task) + raise ArgumentError, 'no block given' unless block_given? + super delayed, 1, Future.new(self, default_executor) + @Executor = executor + @Task = task + @Args = args + end + + def executor + @Executor + end + end + + class ThenPromise < BlockedTaskPromise + private + + def initialize(delayed, blockers_count, default_executor, executor, args, &task) + super delayed, blockers_count, default_executor, executor, args, &task + end + + def on_resolvable(resolved_future, index) + if resolved_future.fulfilled? + Concurrent.executor(@Executor).post(resolved_future, @Args, @Task) do |future, args, task| + evaluate_to lambda { future.apply args, task } + end + else + resolve_with resolved_future.internal_state + end + end + end + + class RescuePromise < BlockedTaskPromise + private + + def initialize(delayed, blockers_count, default_executor, executor, args, &task) + super delayed, blockers_count, default_executor, executor, args, &task + end + + def on_resolvable(resolved_future, index) + if resolved_future.rejected? + Concurrent.executor(@Executor).post(resolved_future, @Args, @Task) do |future, args, task| + evaluate_to lambda { future.apply args, task } + end + else + resolve_with resolved_future.internal_state + end + end + end + + class ChainPromise < BlockedTaskPromise + private + + def on_resolvable(resolved_future, index) + if Future === resolved_future + Concurrent.executor(@Executor).post(resolved_future, @Args, @Task) do |future, args, task| + evaluate_to(*future.result, *args, task) + end + else + Concurrent.executor(@Executor).post(@Args, @Task) do |args, task| + evaluate_to(*args, task) + end + end + end + end + + # will be immediately resolved + class ImmediateEventPromise < InnerPromise + def initialize(default_executor) + super Event.new(self, default_executor).resolve_with(RESOLVED) + end + end + + class ImmediateFuturePromise < InnerPromise + def initialize(default_executor, fulfilled, value, reason) + super Future.new(self, default_executor). + resolve_with(fulfilled ? Fulfilled.new(value) : Rejected.new(reason)) + end + end + + class AbstractFlatPromise < BlockedPromise + + def initialize(delayed_because, blockers_count, event_or_future) + delayed = LockFreeStack.of1(self) + super(delayed, blockers_count, event_or_future) + # noinspection RubyArgCount + @Touched = AtomicBoolean.new false + @DelayedBecause = delayed_because || LockFreeStack.new + + event_or_future.add_callback_clear_delayed_node delayed.peek + end + + def touch + if @Touched.make_true + clear_and_propagate_touch @DelayedBecause + end + end + + private + + def touched? + @Touched.value + end + + def on_resolvable(resolved_future, index) + resolve_with resolved_future.internal_state + end + + def resolvable?(countdown, future, index) + !@Future.internal_state.resolved? && super(countdown, future, index) + end + + def add_delayed_of(future) + delayed = future.promise.delayed_because + if touched? + clear_and_propagate_touch delayed + else + BlockedPromise.add_delayed @DelayedBecause, delayed + clear_and_propagate_touch @DelayedBecause if touched? + end + end + + end + + class FlatEventPromise < AbstractFlatPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super delayed, 2, Event.new(self, default_executor) + end + + def process_on_blocker_resolution(future, index) + countdown = super(future, index) + if countdown.nonzero? + internal_state = future.internal_state + + unless internal_state.fulfilled? + resolve_with RESOLVED + return countdown + end + + value = internal_state.value + case value + when AbstractEventFuture + add_delayed_of value + value.add_callback_notify_blocked self, nil + countdown + else + resolve_with RESOLVED + end + end + countdown + end + + end + + class FlatFuturePromise < AbstractFlatPromise + + private + + def initialize(delayed, blockers_count, levels, default_executor) + raise ArgumentError, 'levels has to be higher than 0' if levels < 1 + # flat promise may result to a future having delayed futures, therefore we have to have empty stack + # to be able to add new delayed futures + super delayed || LockFreeStack.new, 1 + levels, Future.new(self, default_executor) + end + + def process_on_blocker_resolution(future, index) + countdown = super(future, index) + if countdown.nonzero? + internal_state = future.internal_state + + unless internal_state.fulfilled? + resolve_with internal_state + return countdown + end + + value = internal_state.value + case value + when AbstractEventFuture + add_delayed_of value + value.add_callback_notify_blocked self, nil + countdown + else + evaluate_to(lambda { raise TypeError, "returned value #{value.inspect} is not a Future" }) + end + end + countdown + end + + end + + class RunFuturePromise < AbstractFlatPromise + + private + + def initialize(delayed, blockers_count, default_executor, run_test) + super delayed, 1, Future.new(self, default_executor) + @RunTest = run_test + end + + def process_on_blocker_resolution(future, index) + internal_state = future.internal_state + + unless internal_state.fulfilled? + resolve_with internal_state + return 0 + end + + value = internal_state.value + continuation_future = @RunTest.call value + + if continuation_future + add_delayed_of continuation_future + continuation_future.add_callback_notify_blocked self, nil + else + resolve_with internal_state + end + + 1 + end + end + + class ZipEventEventPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor) + super delayed, 2, Event.new(self, default_executor) + end + + private + + def on_resolvable(resolved_future, index) + resolve_with RESOLVED + end + end + + class ZipFutureEventPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor) + super delayed, 2, Future.new(self, default_executor) + @result = nil + end + + private + + def process_on_blocker_resolution(future, index) + # first blocking is future, take its result + @result = future.internal_state if index == 0 + # super has to be called after above to piggyback on volatile @Countdown + super future, index + end + + def on_resolvable(resolved_future, index) + resolve_with @result + end + end + + class EventWrapperPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor) + super delayed, 1, Event.new(self, default_executor) + end + + private + + def on_resolvable(resolved_future, index) + resolve_with RESOLVED + end + end + + class FutureWrapperPromise < BlockedPromise + def initialize(delayed, blockers_count, default_executor) + super delayed, 1, Future.new(self, default_executor) + end + + private + + def on_resolvable(resolved_future, index) + resolve_with resolved_future.internal_state + end + end + + class ZipFuturesPromise < BlockedPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super(delayed, blockers_count, Future.new(self, default_executor)) + @Resolutions = ::Array.new(blockers_count, nil) + + on_resolvable nil, nil if blockers_count == 0 + end + + def process_on_blocker_resolution(future, index) + # TODO (pitr-ch 18-Dec-2016): Can we assume that array will never break under parallel access when never re-sized? + @Resolutions[index] = future.internal_state # has to be set before countdown in super + super future, index + end + + def on_resolvable(resolved_future, index) + all_fulfilled = true + values = ::Array.new(@Resolutions.size) + reasons = ::Array.new(@Resolutions.size) + + @Resolutions.each_with_index do |internal_state, i| + fulfilled, values[i], reasons[i] = internal_state.result + all_fulfilled &&= fulfilled + end + + if all_fulfilled + resolve_with FulfilledArray.new(values) + else + resolve_with PartiallyRejected.new(values, reasons) + end + end + end + + class ZipEventsPromise < BlockedPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super delayed, blockers_count, Event.new(self, default_executor) + + on_resolvable nil, nil if blockers_count == 0 + end + + def on_resolvable(resolved_future, index) + resolve_with RESOLVED + end + end + + # @abstract + class AbstractAnyPromise < BlockedPromise + end + + class AnyResolvedEventPromise < AbstractAnyPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super delayed, blockers_count, Event.new(self, default_executor) + end + + def resolvable?(countdown, future, index) + true + end + + def on_resolvable(resolved_future, index) + resolve_with RESOLVED, false + end + end + + class AnyResolvedFuturePromise < AbstractAnyPromise + + private + + def initialize(delayed, blockers_count, default_executor) + super delayed, blockers_count, Future.new(self, default_executor) + end + + def resolvable?(countdown, future, index) + true + end + + def on_resolvable(resolved_future, index) + resolve_with resolved_future.internal_state, false + end + end + + class AnyFulfilledFuturePromise < AnyResolvedFuturePromise + + private + + def resolvable?(countdown, event_or_future, index) + (event_or_future.is_a?(Event) ? event_or_future.resolved? : event_or_future.fulfilled?) || + # inlined super from BlockedPromise + countdown.zero? + end + end + + class DelayPromise < InnerPromise + + def initialize(default_executor) + event = Event.new(self, default_executor) + @Delayed = LockFreeStack.of1(self) + super event + event.add_callback_clear_delayed_node @Delayed.peek + end + + def touch + @Future.resolve_with RESOLVED + end + + def delayed_because + @Delayed + end + + end + + class ScheduledPromise < InnerPromise + def intended_time + @IntendedTime + end + + def inspect + "#{to_s[0..-2]} intended_time: #{@IntendedTime}>" + end + + private + + def initialize(default_executor, intended_time) + super Event.new(self, default_executor) + + @IntendedTime = intended_time + + in_seconds = begin + now = Time.now + schedule_time = if @IntendedTime.is_a? Time + @IntendedTime + else + now + @IntendedTime + end + [0, schedule_time.to_f - now.to_f].max + end + + Concurrent.global_timer_set.post(in_seconds) do + @Future.resolve_with RESOLVED + end + end + end + + extend FactoryMethods + + private_constant :AbstractPromise, + :ResolvableEventPromise, + :ResolvableFuturePromise, + :InnerPromise, + :BlockedPromise, + :BlockedTaskPromise, + :ThenPromise, + :RescuePromise, + :ChainPromise, + :ImmediateEventPromise, + :ImmediateFuturePromise, + :AbstractFlatPromise, + :FlatFuturePromise, + :FlatEventPromise, + :RunFuturePromise, + :ZipEventEventPromise, + :ZipFutureEventPromise, + :EventWrapperPromise, + :FutureWrapperPromise, + :ZipFuturesPromise, + :ZipEventsPromise, + :AbstractAnyPromise, + :AnyResolvedFuturePromise, + :AnyFulfilledFuturePromise, + :AnyResolvedEventPromise, + :DelayPromise, + :ScheduledPromise + + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/re_include.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/re_include.rb new file mode 100644 index 0000000000000..600bc6a53568c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/re_include.rb @@ -0,0 +1,60 @@ +module Concurrent + + # Methods form module A included to a module B, which is already included into class C, + # will not be visible in the C class. If this module is extended to B then A's methods + # are correctly made visible to C. + # + # @example + # module A + # def a + # :a + # end + # end + # + # module B1 + # end + # + # class C1 + # include B1 + # end + # + # module B2 + # extend Concurrent::ReInclude + # end + # + # class C2 + # include B2 + # end + # + # B1.send :include, A + # B2.send :include, A + # + # C1.new.respond_to? :a # => false + # C2.new.respond_to? :a # => true + # + # @!visibility private + module ReInclude + # @!visibility private + def included(base) + (@re_include_to_bases ||= []) << [:include, base] + super(base) + end + + # @!visibility private + def extended(base) + (@re_include_to_bases ||= []) << [:extend, base] + super(base) + end + + # @!visibility private + def include(*modules) + result = super(*modules) + modules.reverse.each do |module_being_included| + (@re_include_to_bases ||= []).each do |method, mod| + mod.send method, module_being_included + end + end + result + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/scheduled_task.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/scheduled_task.rb new file mode 100644 index 0000000000000..429fc0683c6f2 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/scheduled_task.rb @@ -0,0 +1,331 @@ +require 'concurrent/constants' +require 'concurrent/errors' +require 'concurrent/configuration' +require 'concurrent/ivar' +require 'concurrent/collection/copy_on_notify_observer_set' +require 'concurrent/utility/monotonic_time' + +require 'concurrent/options' + +module Concurrent + + # `ScheduledTask` is a close relative of `Concurrent::Future` but with one + # important difference: A `Future` is set to execute as soon as possible + # whereas a `ScheduledTask` is set to execute after a specified delay. This + # implementation is loosely based on Java's + # [ScheduledExecutorService](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html). + # It is a more feature-rich variant of {Concurrent.timer}. + # + # The *intended* schedule time of task execution is set on object construction + # with the `delay` argument. The delay is a numeric (floating point or integer) + # representing a number of seconds in the future. Any other value or a numeric + # equal to or less than zero will result in an exception. The *actual* schedule + # time of task execution is set when the `execute` method is called. + # + # The constructor can also be given zero or more processing options. Currently + # the only supported options are those recognized by the + # [Dereferenceable](Dereferenceable) module. + # + # The final constructor argument is a block representing the task to be performed. + # If no block is given an `ArgumentError` will be raised. + # + # **States** + # + # `ScheduledTask` mixes in the [Obligation](Obligation) module thus giving it + # "future" behavior. This includes the expected lifecycle states. `ScheduledTask` + # has one additional state, however. While the task (block) is being executed the + # state of the object will be `:processing`. This additional state is necessary + # because it has implications for task cancellation. + # + # **Cancellation** + # + # A `:pending` task can be cancelled using the `#cancel` method. A task in any + # other state, including `:processing`, cannot be cancelled. The `#cancel` + # method returns a boolean indicating the success of the cancellation attempt. + # A cancelled `ScheduledTask` cannot be restarted. It is immutable. + # + # **Obligation and Observation** + # + # The result of a `ScheduledTask` can be obtained either synchronously or + # asynchronously. `ScheduledTask` mixes in both the [Obligation](Obligation) + # module and the + # [Observable](http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html) + # module from the Ruby standard library. With one exception `ScheduledTask` + # behaves identically to [Future](Observable) with regard to these modules. + # + # @!macro copy_options + # + # @example Basic usage + # + # require 'concurrent/scheduled_task' + # require 'csv' + # require 'open-uri' + # + # class Ticker + # def get_year_end_closing(symbol, year, api_key) + # uri = "https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=#{symbol}&apikey=#{api_key}&datatype=csv" + # data = [] + # csv = URI.parse(uri).read + # if csv.include?('call frequency') + # return :rate_limit_exceeded + # end + # CSV.parse(csv, headers: true) do |row| + # data << row['close'].to_f if row['timestamp'].include?(year.to_s) + # end + # year_end = data.first + # year_end + # rescue => e + # p e + # end + # end + # + # api_key = ENV['ALPHAVANTAGE_KEY'] + # abort(error_message) unless api_key + # + # # Future + # price = Concurrent::Future.execute{ Ticker.new.get_year_end_closing('TWTR', 2013, api_key) } + # price.state #=> :pending + # price.pending? #=> true + # price.value(0) #=> nil (does not block) + # + # sleep(1) # do other stuff + # + # price.value #=> 63.65 (after blocking if necessary) + # price.state #=> :fulfilled + # price.fulfilled? #=> true + # price.value #=> 63.65 + # + # @example Successful task execution + # + # task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' } + # task.state #=> :unscheduled + # task.execute + # task.state #=> pending + # + # # wait for it... + # sleep(3) + # + # task.unscheduled? #=> false + # task.pending? #=> false + # task.fulfilled? #=> true + # task.rejected? #=> false + # task.value #=> 'What does the fox say?' + # + # @example One line creation and execution + # + # task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' }.execute + # task.state #=> pending + # + # task = Concurrent::ScheduledTask.execute(2){ 'What do you get when you multiply 6 by 9?' } + # task.state #=> pending + # + # @example Failed task execution + # + # task = Concurrent::ScheduledTask.execute(2){ raise StandardError.new('Call me maybe?') } + # task.pending? #=> true + # + # # wait for it... + # sleep(3) + # + # task.unscheduled? #=> false + # task.pending? #=> false + # task.fulfilled? #=> false + # task.rejected? #=> true + # task.value #=> nil + # task.reason #=> # + # + # @example Task execution with observation + # + # observer = Class.new{ + # def update(time, value, reason) + # puts "The task completed at #{time} with value '#{value}'" + # end + # }.new + # + # task = Concurrent::ScheduledTask.new(2){ 'What does the fox say?' } + # task.add_observer(observer) + # task.execute + # task.pending? #=> true + # + # # wait for it... + # sleep(3) + # + # #>> The task completed at 2013-11-07 12:26:09 -0500 with value 'What does the fox say?' + # + # @!macro monotonic_clock_warning + # + # @see Concurrent.timer + class ScheduledTask < IVar + include Comparable + + # The executor on which to execute the task. + # @!visibility private + attr_reader :executor + + # Schedule a task for execution at a specified future time. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @yield the task to be performed + # + # @!macro executor_and_deref_options + # + # @option opts [object, Array] :args zero or more arguments to be passed the task + # block on execution + # + # @raise [ArgumentError] When no block is given + # @raise [ArgumentError] When given a time that is in the past + def initialize(delay, opts = {}, &task) + raise ArgumentError.new('no block given') unless block_given? + raise ArgumentError.new('seconds must be greater than zero') if delay.to_f < 0.0 + + super(NULL, opts, &nil) + + synchronize do + ns_set_state(:unscheduled) + @parent = opts.fetch(:timer_set, Concurrent.global_timer_set) + @args = get_arguments_from(opts) + @delay = delay.to_f + @task = task + @time = nil + @executor = Options.executor_from_options(opts) || Concurrent.global_io_executor + self.observers = Collection::CopyOnNotifyObserverSet.new + end + end + + # The `delay` value given at instanciation. + # + # @return [Float] the initial delay. + def initial_delay + synchronize { @delay } + end + + # The monotonic time at which the the task is scheduled to be executed. + # + # @return [Float] the schedule time or nil if `unscheduled` + def schedule_time + synchronize { @time } + end + + # Comparator which orders by schedule time. + # + # @!visibility private + def <=>(other) + schedule_time <=> other.schedule_time + end + + # Has the task been cancelled? + # + # @return [Boolean] true if the task is in the given state else false + def cancelled? + synchronize { ns_check_state?(:cancelled) } + end + + # In the task execution in progress? + # + # @return [Boolean] true if the task is in the given state else false + def processing? + synchronize { ns_check_state?(:processing) } + end + + # Cancel this task and prevent it from executing. A task can only be + # cancelled if it is pending or unscheduled. + # + # @return [Boolean] true if successfully cancelled else false + def cancel + if compare_and_set_state(:cancelled, :pending, :unscheduled) + complete(false, nil, CancelledOperationError.new) + # To avoid deadlocks this call must occur outside of #synchronize + # Changing the state above should prevent redundant calls + @parent.send(:remove_task, self) + else + false + end + end + + # Reschedule the task using the original delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @return [Boolean] true if successfully rescheduled else false + def reset + synchronize{ ns_reschedule(@delay) } + end + + # Reschedule the task using the given delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @return [Boolean] true if successfully rescheduled else false + # + # @raise [ArgumentError] When given a time that is in the past + def reschedule(delay) + delay = delay.to_f + raise ArgumentError.new('seconds must be greater than zero') if delay < 0.0 + synchronize{ ns_reschedule(delay) } + end + + # Execute an `:unscheduled` `ScheduledTask`. Immediately sets the state to `:pending` + # and starts counting down toward execution. Does nothing if the `ScheduledTask` is + # in any state other than `:unscheduled`. + # + # @return [ScheduledTask] a reference to `self` + def execute + if compare_and_set_state(:pending, :unscheduled) + synchronize{ ns_schedule(@delay) } + end + self + end + + # Create a new `ScheduledTask` object with the given block, execute it, and return the + # `:pending` object. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @!macro executor_and_deref_options + # + # @return [ScheduledTask] the newly created `ScheduledTask` in the `:pending` state + # + # @raise [ArgumentError] if no block is given + def self.execute(delay, opts = {}, &task) + new(delay, opts, &task).execute + end + + # Execute the task. + # + # @!visibility private + def process_task + safe_execute(@task, @args) + end + + protected :set, :try_set, :fail, :complete + + protected + + # Schedule the task using the given delay and the current time. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @return [Boolean] true if successfully rescheduled else false + # + # @!visibility private + def ns_schedule(delay) + @delay = delay + @time = Concurrent.monotonic_time + @delay + @parent.send(:post_task, self) + end + + # Reschedule the task using the given delay and the current time. + # A task can only be reset while it is `:pending`. + # + # @param [Float] delay the number of seconds to wait for before executing the task + # + # @return [Boolean] true if successfully rescheduled else false + # + # @!visibility private + def ns_reschedule(delay) + return false unless ns_check_state?(:pending) + @parent.send(:remove_task, self) && ns_schedule(delay) + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/set.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/set.rb new file mode 100644 index 0000000000000..eee4effdfd2d6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/set.rb @@ -0,0 +1,64 @@ +require 'concurrent/utility/engine' +require 'concurrent/thread_safe/util' +require 'set' + +module Concurrent + + # @!macro concurrent_set + # + # A thread-safe subclass of Set. This version locks against the object + # itself for every method call, ensuring only one thread can be reading + # or writing at a time. This includes iteration methods like `#each`. + # + # @note `a += b` is **not** a **thread-safe** operation on + # `Concurrent::Set`. It reads Set `a`, then it creates new `Concurrent::Set` + # which is union of `a` and `b`, then it writes the union to `a`. + # The read and write are independent operations they do not form a single atomic + # operation therefore when two `+=` operations are executed concurrently updates + # may be lost. Use `#merge` instead. + # + # @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set` + + # @!macro internal_implementation_note + SetImplementation = case + when Concurrent.on_cruby? + # The CRuby implementation of Set is written in Ruby itself and is + # not thread safe for certain methods. + require 'monitor' + require 'concurrent/thread_safe/util/data_structures' + + class CRubySet < ::Set + end + + ThreadSafe::Util.make_synchronized_on_cruby CRubySet + CRubySet + + when Concurrent.on_jruby? + require 'jruby/synchronized' + + class JRubySet < ::Set + include JRuby::Synchronized + end + + JRubySet + + when Concurrent.on_truffleruby? + require 'concurrent/thread_safe/util/data_structures' + + class TruffleRubySet < ::Set + end + + ThreadSafe::Util.make_synchronized_on_truffleruby TruffleRubySet + TruffleRubySet + + else + warn 'Possibly unsupported Ruby implementation' + ::Set + end + private_constant :SetImplementation + + # @!macro concurrent_set + class Set < SetImplementation + end +end + diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/settable_struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/settable_struct.rb new file mode 100644 index 0000000000000..99b85619fd370 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/settable_struct.rb @@ -0,0 +1,139 @@ +require 'concurrent/errors' +require 'concurrent/synchronization/abstract_struct' +require 'concurrent/synchronization/lockable_object' + +module Concurrent + + # An thread-safe, write-once variation of Ruby's standard `Struct`. + # Each member can have its value set at most once, either at construction + # or any time thereafter. Attempting to assign a value to a member + # that has already been set will result in a `Concurrent::ImmutabilityError`. + # + # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct` + # @see http://en.wikipedia.org/wiki/Final_(Java) Java `final` keyword + module SettableStruct + include Synchronization::AbstractStruct + + # @!macro struct_values + def values + synchronize { ns_values } + end + alias_method :to_a, :values + + # @!macro struct_values_at + def values_at(*indexes) + synchronize { ns_values_at(indexes) } + end + + # @!macro struct_inspect + def inspect + synchronize { ns_inspect } + end + alias_method :to_s, :inspect + + # @!macro struct_merge + def merge(other, &block) + synchronize { ns_merge(other, &block) } + end + + # @!macro struct_to_h + def to_h + synchronize { ns_to_h } + end + + # @!macro struct_get + def [](member) + synchronize { ns_get(member) } + end + + # @!macro struct_equality + def ==(other) + synchronize { ns_equality(other) } + end + + # @!macro struct_each + def each(&block) + return enum_for(:each) unless block_given? + synchronize { ns_each(&block) } + end + + # @!macro struct_each_pair + def each_pair(&block) + return enum_for(:each_pair) unless block_given? + synchronize { ns_each_pair(&block) } + end + + # @!macro struct_select + def select(&block) + return enum_for(:select) unless block_given? + synchronize { ns_select(&block) } + end + + # @!macro struct_set + # + # @raise [Concurrent::ImmutabilityError] if the given member has already been set + def []=(member, value) + if member.is_a? Integer + length = synchronize { @values.length } + if member >= length + raise IndexError.new("offset #{member} too large for struct(size:#{length})") + end + synchronize do + unless @values[member].nil? + raise Concurrent::ImmutabilityError.new('struct member has already been set') + end + @values[member] = value + end + else + send("#{member}=", value) + end + rescue NoMethodError + raise NameError.new("no member '#{member}' in struct") + end + + private + + # @!visibility private + def initialize_copy(original) + synchronize do + super(original) + ns_initialize_copy + end + end + + # @!macro struct_new + def self.new(*args, &block) + clazz_name = nil + if args.length == 0 + raise ArgumentError.new('wrong number of arguments (0 for 1+)') + elsif args.length > 0 && args.first.is_a?(String) + clazz_name = args.shift + end + FACTORY.define_struct(clazz_name, args, &block) + end + + FACTORY = Class.new(Synchronization::LockableObject) do + def define_struct(name, members, &block) + synchronize do + clazz = Synchronization::AbstractStruct.define_struct_class(SettableStruct, Synchronization::LockableObject, name, members, &block) + members.each_with_index do |member, index| + clazz.send :remove_method, member if clazz.instance_methods.include? member + clazz.send(:define_method, member) do + synchronize { @values[index] } + end + clazz.send(:define_method, "#{member}=") do |value| + synchronize do + unless @values[index].nil? + raise Concurrent::ImmutabilityError.new('struct member has already been set') + end + @values[index] = value + end + end + end + clazz + end + end + end.new + private_constant :FACTORY + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization.rb new file mode 100644 index 0000000000000..6d8cf4bd584d4 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization.rb @@ -0,0 +1,13 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/synchronization/object' +require 'concurrent/synchronization/lockable_object' +require 'concurrent/synchronization/condition' +require 'concurrent/synchronization/lock' + +module Concurrent + # @!visibility private + module Synchronization + end +end + diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb new file mode 100644 index 0000000000000..d9050b312fd45 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb @@ -0,0 +1,102 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first +require 'concurrent/utility/monotonic_time' +require 'concurrent/synchronization/object' + +module Concurrent + module Synchronization + + # @!visibility private + class AbstractLockableObject < Synchronization::Object + + protected + + # @!macro synchronization_object_method_synchronize + # + # @yield runs the block synchronized against this object, + # equivalent of java's `synchronize(this) {}` + # @note can by made public in descendants if required by `public :synchronize` + def synchronize + raise NotImplementedError + end + + # @!macro synchronization_object_method_ns_wait_until + # + # Wait until condition is met or timeout passes, + # protects against spurious wake-ups. + # @param [Numeric, nil] timeout in seconds, `nil` means no timeout + # @yield condition to be met + # @yieldreturn [true, false] + # @return [true, false] if condition met + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def wait_until(timeout = nil, &condition) + # synchronize { ns_wait_until(timeout, &condition) } + # end + # ``` + def ns_wait_until(timeout = nil, &condition) + if timeout + wait_until = Concurrent.monotonic_time + timeout + loop do + now = Concurrent.monotonic_time + condition_result = condition.call + return condition_result if now >= wait_until || condition_result + ns_wait wait_until - now + end + else + ns_wait timeout until condition.call + true + end + end + + # @!macro synchronization_object_method_ns_wait + # + # Wait until another thread calls #signal or #broadcast, + # spurious wake-ups can happen. + # + # @param [Numeric, nil] timeout in seconds, `nil` means no timeout + # @return [self] + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def wait(timeout = nil) + # synchronize { ns_wait(timeout) } + # end + # ``` + def ns_wait(timeout = nil) + raise NotImplementedError + end + + # @!macro synchronization_object_method_ns_signal + # + # Signal one waiting thread. + # @return [self] + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def signal + # synchronize { ns_signal } + # end + # ``` + def ns_signal + raise NotImplementedError + end + + # @!macro synchronization_object_method_ns_broadcast + # + # Broadcast to all waiting threads. + # @return [self] + # @note only to be used inside synchronized block + # @note to provide direct access to this method in a descendant add method + # ``` + # def broadcast + # synchronize { ns_broadcast } + # end + # ``` + def ns_broadcast + raise NotImplementedError + end + + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb new file mode 100644 index 0000000000000..7cd2decf99ca5 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb @@ -0,0 +1,22 @@ +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + class AbstractObject + def initialize + # nothing to do + end + + # @!visibility private + # @abstract + def full_memory_barrier + raise NotImplementedError + end + + def self.attr_volatile(*names) + raise NotImplementedError + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb new file mode 100644 index 0000000000000..1fe90c1649bf8 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb @@ -0,0 +1,171 @@ +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + module AbstractStruct + + # @!visibility private + def initialize(*values) + super() + ns_initialize(*values) + end + + # @!macro struct_length + # + # Returns the number of struct members. + # + # @return [Fixnum] the number of struct members + def length + self.class::MEMBERS.length + end + alias_method :size, :length + + # @!macro struct_members + # + # Returns the struct members as an array of symbols. + # + # @return [Array] the struct members as an array of symbols + def members + self.class::MEMBERS.dup + end + + protected + + # @!macro struct_values + # + # @!visibility private + def ns_values + @values.dup + end + + # @!macro struct_values_at + # + # @!visibility private + def ns_values_at(indexes) + @values.values_at(*indexes) + end + + # @!macro struct_to_h + # + # @!visibility private + def ns_to_h + length.times.reduce({}){|memo, i| memo[self.class::MEMBERS[i]] = @values[i]; memo} + end + + # @!macro struct_get + # + # @!visibility private + def ns_get(member) + if member.is_a? Integer + if member >= @values.length + raise IndexError.new("offset #{member} too large for struct(size:#{@values.length})") + end + @values[member] + else + send(member) + end + rescue NoMethodError + raise NameError.new("no member '#{member}' in struct") + end + + # @!macro struct_equality + # + # @!visibility private + def ns_equality(other) + self.class == other.class && self.values == other.values + end + + # @!macro struct_each + # + # @!visibility private + def ns_each + values.each{|value| yield value } + end + + # @!macro struct_each_pair + # + # @!visibility private + def ns_each_pair + @values.length.times do |index| + yield self.class::MEMBERS[index], @values[index] + end + end + + # @!macro struct_select + # + # @!visibility private + def ns_select + values.select{|value| yield value } + end + + # @!macro struct_inspect + # + # @!visibility private + def ns_inspect + struct = pr_underscore(self.class.ancestors[1]) + clazz = ((self.class.to_s =~ /^#" + end + + # @!macro struct_merge + # + # @!visibility private + def ns_merge(other, &block) + self.class.new(*self.to_h.merge(other, &block).values) + end + + # @!visibility private + def ns_initialize_copy + @values = @values.map do |val| + begin + val.clone + rescue TypeError + val + end + end + end + + # @!visibility private + def pr_underscore(clazz) + word = clazz.to_s.dup # dup string to workaround JRuby 9.2.0.0 bug https://github.com/jruby/jruby/issues/5229 + word.gsub!(/::/, '/') + word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') + word.gsub!(/([a-z\d])([A-Z])/,'\1_\2') + word.tr!("-", "_") + word.downcase! + word + end + + # @!visibility private + def self.define_struct_class(parent, base, name, members, &block) + clazz = Class.new(base || Object) do + include parent + self.const_set(:MEMBERS, members.collect{|member| member.to_s.to_sym}.freeze) + def ns_initialize(*values) + raise ArgumentError.new('struct size differs') if values.length > length + @values = values.fill(nil, values.length..length-1) + end + end + unless name.nil? + begin + parent.send :remove_const, name if parent.const_defined?(name, false) + parent.const_set(name, clazz) + clazz + rescue NameError + raise NameError.new("identifier #{name} needs to be constant") + end + end + members.each_with_index do |member, index| + clazz.send :remove_method, member if clazz.instance_methods.include? member + clazz.send(:define_method, member) do + @values[index] + end + end + clazz.class_exec(&block) unless block.nil? + clazz.singleton_class.send :alias_method, :[], :new + clazz + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/condition.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/condition.rb new file mode 100644 index 0000000000000..5daa68be8ab54 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/condition.rb @@ -0,0 +1,62 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + module Synchronization + + # @!visibility private + # TODO (pitr-ch 04-Dec-2016): should be in edge + class Condition < LockableObject + safe_initialization! + + # TODO (pitr 12-Sep-2015): locks two objects, improve + # TODO (pitr 26-Sep-2015): study + # http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/concurrent/locks/AbstractQueuedSynchronizer.java#AbstractQueuedSynchronizer.Node + + singleton_class.send :alias_method, :private_new, :new + private_class_method :new + + def initialize(lock) + super() + @Lock = lock + end + + def wait(timeout = nil) + @Lock.synchronize { ns_wait(timeout) } + end + + def ns_wait(timeout = nil) + synchronize { super(timeout) } + end + + def wait_until(timeout = nil, &condition) + @Lock.synchronize { ns_wait_until(timeout, &condition) } + end + + def ns_wait_until(timeout = nil, &condition) + synchronize { super(timeout, &condition) } + end + + def signal + @Lock.synchronize { ns_signal } + end + + def ns_signal + synchronize { super } + end + + def broadcast + @Lock.synchronize { ns_broadcast } + end + + def ns_broadcast + synchronize { super } + end + end + + class LockableObject < LockableObjectImplementation + def new_condition + Condition.private_new(self) + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb new file mode 100644 index 0000000000000..139e08d854e01 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb @@ -0,0 +1,29 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +module Concurrent + module Synchronization + case + when Concurrent.on_cruby? + def self.full_memory_barrier + # relying on undocumented behavior of CRuby, GVL acquire has lock which ensures visibility of ivars + # https://github.com/ruby/ruby/blob/ruby_2_2/thread_pthread.c#L204-L211 + end + + when Concurrent.on_jruby? + require 'concurrent/utility/native_extension_loader' + def self.full_memory_barrier + JRubyAttrVolatile.full_memory_barrier + end + + when Concurrent.on_truffleruby? + def self.full_memory_barrier + TruffleRuby.full_memory_barrier + end + + else + warn 'Possibly unsupported Ruby implementation' + def self.full_memory_barrier + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb new file mode 100644 index 0000000000000..76930461bdb8c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb @@ -0,0 +1,15 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +module Concurrent + module Synchronization + + if Concurrent.on_jruby? + + # @!visibility private + # @!macro internal_implementation_note + class JRubyLockableObject < AbstractLockableObject + + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lock.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lock.rb new file mode 100644 index 0000000000000..f90e0b5f76872 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lock.rb @@ -0,0 +1,38 @@ +require 'concurrent/synchronization/lockable_object' + +module Concurrent + module Synchronization + + # @!visibility private + # TODO (pitr-ch 04-Dec-2016): should be in edge + class Lock < LockableObject + # TODO use JavaReentrantLock on JRuby + + public :synchronize + + def wait(timeout = nil) + synchronize { ns_wait(timeout) } + end + + public :ns_wait + + def wait_until(timeout = nil, &condition) + synchronize { ns_wait_until(timeout, &condition) } + end + + public :ns_wait_until + + def signal + synchronize { ns_signal } + end + + public :ns_signal + + def broadcast + synchronize { ns_broadcast } + end + + public :ns_broadcast + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb new file mode 100644 index 0000000000000..08d2ff66cd824 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb @@ -0,0 +1,75 @@ +require 'concurrent/utility/engine' +require 'concurrent/synchronization/abstract_lockable_object' +require 'concurrent/synchronization/mutex_lockable_object' +require 'concurrent/synchronization/jruby_lockable_object' + +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + LockableObjectImplementation = case + when Concurrent.on_cruby? + MutexLockableObject + when Concurrent.on_jruby? + JRubyLockableObject + when Concurrent.on_truffleruby? + MutexLockableObject + else + warn 'Possibly unsupported Ruby implementation' + MonitorLockableObject + end + private_constant :LockableObjectImplementation + + # Safe synchronization under any Ruby implementation. + # It provides methods like {#synchronize}, {#wait}, {#signal} and {#broadcast}. + # Provides a single layer which can improve its implementation over time without changes needed to + # the classes using it. Use {Synchronization::Object} not this abstract class. + # + # @note this object does not support usage together with + # [`Thread#wakeup`](http://ruby-doc.org/core/Thread.html#method-i-wakeup) + # and [`Thread#raise`](http://ruby-doc.org/core/Thread.html#method-i-raise). + # `Thread#sleep` and `Thread#wakeup` will work as expected but mixing `Synchronization::Object#wait` and + # `Thread#wakeup` will not work on all platforms. + # + # @see Event implementation as an example of this class use + # + # @example simple + # class AnClass < Synchronization::Object + # def initialize + # super + # synchronize { @value = 'asd' } + # end + # + # def value + # synchronize { @value } + # end + # end + # + # @!visibility private + class LockableObject < LockableObjectImplementation + + # TODO (pitr 12-Sep-2015): make private for c-r, prohibit subclassing + # TODO (pitr 12-Sep-2015): we inherit too much ourselves :/ + + # @!method initialize(*args, &block) + # @!macro synchronization_object_method_initialize + + # @!method synchronize + # @!macro synchronization_object_method_synchronize + + # @!method wait_until(timeout = nil, &condition) + # @!macro synchronization_object_method_ns_wait_until + + # @!method wait(timeout = nil) + # @!macro synchronization_object_method_ns_wait + + # @!method signal + # @!macro synchronization_object_method_ns_signal + + # @!method broadcast + # @!macro synchronization_object_method_ns_broadcast + + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb new file mode 100644 index 0000000000000..acc9745a2e292 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb @@ -0,0 +1,89 @@ +require 'concurrent/synchronization/abstract_lockable_object' + +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + module ConditionSignalling + protected + + def ns_signal + @__Condition__.signal + self + end + + def ns_broadcast + @__Condition__.broadcast + self + end + end + + + # @!visibility private + # @!macro internal_implementation_note + class MutexLockableObject < AbstractLockableObject + include ConditionSignalling + + safe_initialization! + + def initialize + super() + @__Lock__ = ::Mutex.new + @__Condition__ = ::ConditionVariable.new + end + + def initialize_copy(other) + super + @__Lock__ = ::Mutex.new + @__Condition__ = ::ConditionVariable.new + end + + protected + + def synchronize + if @__Lock__.owned? + yield + else + @__Lock__.synchronize { yield } + end + end + + def ns_wait(timeout = nil) + @__Condition__.wait @__Lock__, timeout + self + end + end + + # @!visibility private + # @!macro internal_implementation_note + class MonitorLockableObject < AbstractLockableObject + include ConditionSignalling + + safe_initialization! + + def initialize + super() + @__Lock__ = ::Monitor.new + @__Condition__ = @__Lock__.new_cond + end + + def initialize_copy(other) + super + @__Lock__ = ::Monitor.new + @__Condition__ = @__Lock__.new_cond + end + + protected + + def synchronize # TODO may be a problem with lock.synchronize { lock.wait } + @__Lock__.synchronize { yield } + end + + def ns_wait(timeout = nil) + @__Condition__.wait timeout + self + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/object.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/object.rb new file mode 100644 index 0000000000000..e839c9f18890f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/object.rb @@ -0,0 +1,151 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first + +require 'concurrent/synchronization/safe_initialization' +require 'concurrent/synchronization/volatile' +require 'concurrent/atomic/atomic_reference' + +module Concurrent + module Synchronization + + # Abstract object providing final, volatile, ans CAS extensions to build other concurrent abstractions. + # - final instance variables see {Object.safe_initialization!} + # - volatile instance variables see {Object.attr_volatile} + # - volatile instance variables see {Object.attr_atomic} + # @!visibility private + class Object < AbstractObject + include Volatile + + # TODO make it a module if possible + + # @!method self.attr_volatile(*names) + # Creates methods for reading and writing (as `attr_accessor` does) to a instance variable with + # volatile (Java) semantic. The instance variable should be accessed only through generated methods. + # + # @param [::Array] names of the instance variables to be volatile + # @return [::Array] names of defined method names + + # Has to be called by children. + def initialize + super + __initialize_atomic_fields__ + end + + def self.safe_initialization! + extend SafeInitialization unless safe_initialization? + end + + def self.safe_initialization? + self.singleton_class < SafeInitialization + end + + # For testing purposes, quite slow. Injects assert code to new method which will raise if class instance contains + # any instance variables with CamelCase names and isn't {.safe_initialization?}. + # @raise when offend found + # @return [true] + def self.ensure_safe_initialization_when_final_fields_are_present + Object.class_eval do + def self.new(*args, &block) + object = super(*args, &block) + ensure + has_final_field = object.instance_variables.any? { |v| v.to_s =~ /^@[A-Z]/ } + if has_final_field && !safe_initialization? + raise "there was an instance of #{object.class} with final field but not marked with safe_initialization!" + end + end + end + true + end + + # Creates methods for reading and writing to a instance variable with + # volatile (Java) semantic as {.attr_volatile} does. + # The instance variable should be accessed oly through generated methods. + # This method generates following methods: `value`, `value=(new_value) #=> new_value`, + # `swap_value(new_value) #=> old_value`, + # `compare_and_set_value(expected, value) #=> true || false`, `update_value(&block)`. + # @param [::Array] names of the instance variables to be volatile with CAS. + # @return [::Array] names of defined method names. + # @!macro attr_atomic + # @!method $1 + # @return [Object] The $1. + # @!method $1=(new_$1) + # Set the $1. + # @return [Object] new_$1. + # @!method swap_$1(new_$1) + # Set the $1 to new_$1 and return the old $1. + # @return [Object] old $1 + # @!method compare_and_set_$1(expected_$1, new_$1) + # Sets the $1 to new_$1 if the current $1 is expected_$1 + # @return [true, false] + # @!method update_$1(&block) + # Updates the $1 using the block. + # @yield [Object] Calculate a new $1 using given (old) $1 + # @yieldparam [Object] old $1 + # @return [Object] new $1 + def self.attr_atomic(*names) + @__atomic_fields__ ||= [] + @__atomic_fields__ += names + safe_initialization! + define_initialize_atomic_fields + + names.each do |name| + ivar = :"@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }}" + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{name} + #{ivar}.get + end + + def #{name}=(value) + #{ivar}.set value + end + + def swap_#{name}(value) + #{ivar}.swap value + end + + def compare_and_set_#{name}(expected, value) + #{ivar}.compare_and_set expected, value + end + + def update_#{name}(&block) + #{ivar}.update(&block) + end + RUBY + end + names.flat_map { |n| [n, :"#{n}=", :"swap_#{n}", :"compare_and_set_#{n}", :"update_#{n}"] } + end + + # @param [true, false] inherited should inherited volatile with CAS fields be returned? + # @return [::Array] Returns defined volatile with CAS fields on this class. + def self.atomic_attributes(inherited = true) + @__atomic_fields__ ||= [] + ((superclass.atomic_attributes if superclass.respond_to?(:atomic_attributes) && inherited) || []) + @__atomic_fields__ + end + + # @return [true, false] is the attribute with name atomic? + def self.atomic_attribute?(name) + atomic_attributes.include? name + end + + private + + def self.define_initialize_atomic_fields + assignments = @__atomic_fields__.map do |name| + "@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }} = Concurrent::AtomicReference.new(nil)" + end.join("\n") + + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def __initialize_atomic_fields__ + super + #{assignments} + end + RUBY + end + + private_class_method :define_initialize_atomic_fields + + def __initialize_atomic_fields__ + end + + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb new file mode 100644 index 0000000000000..f785e35229fa3 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb @@ -0,0 +1,36 @@ +require 'concurrent/synchronization/full_memory_barrier' + +module Concurrent + module Synchronization + + # @!visibility private + # @!macro internal_implementation_note + # + # By extending this module, a class and all its children are marked to be constructed safely. Meaning that + # all writes (ivar initializations) are made visible to all readers of newly constructed object. It ensures + # same behaviour as Java's final fields. + # + # Due to using Kernel#extend, the module is not included again if already present in the ancestors, + # which avoids extra overhead. + # + # @example + # class AClass < Concurrent::Synchronization::Object + # extend Concurrent::Synchronization::SafeInitialization + # + # def initialize + # @AFinalValue = 'value' # published safely, #foo will never return nil + # end + # + # def foo + # @AFinalValue + # end + # end + module SafeInitialization + def new(*args, &block) + super(*args, &block) + ensure + Concurrent::Synchronization.full_memory_barrier + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/volatile.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/volatile.rb new file mode 100644 index 0000000000000..46e8ba6a48ca1 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/synchronization/volatile.rb @@ -0,0 +1,101 @@ +require 'concurrent/utility/native_extension_loader' # load native parts first +require 'concurrent/utility/engine' +require 'concurrent/synchronization/full_memory_barrier' + +module Concurrent + module Synchronization + + # Volatile adds the attr_volatile class method when included. + # + # @example + # class Foo + # include Concurrent::Synchronization::Volatile + # + # attr_volatile :bar + # + # def initialize + # self.bar = 1 + # end + # end + # + # foo = Foo.new + # foo.bar + # => 1 + # foo.bar = 2 + # => 2 + # + # @!visibility private + module Volatile + def self.included(base) + base.extend(ClassMethods) + end + + def full_memory_barrier + Synchronization.full_memory_barrier + end + + module ClassMethods + if Concurrent.on_cruby? + def attr_volatile(*names) + names.each do |name| + ivar = :"@volatile_#{name}" + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{name} + #{ivar} + end + + def #{name}=(value) + #{ivar} = value + end + RUBY + end + names.map { |n| [n, :"#{n}="] }.flatten + end + + elsif Concurrent.on_jruby? + def attr_volatile(*names) + names.each do |name| + ivar = :"@volatile_#{name}" + + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{name} + ::Concurrent::Synchronization::JRubyAttrVolatile.instance_variable_get_volatile(self, :#{ivar}) + end + + def #{name}=(value) + ::Concurrent::Synchronization::JRubyAttrVolatile.instance_variable_set_volatile(self, :#{ivar}, value) + end + RUBY + + end + names.map { |n| [n, :"#{n}="] }.flatten + end + + else + warn 'Possibly unsupported Ruby implementation' unless Concurrent.on_truffleruby? + + def attr_volatile(*names) + names.each do |name| + ivar = :"@volatile_#{name}" + + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{name} + ::Concurrent::Synchronization.full_memory_barrier + #{ivar} + end + + def #{name}=(value) + #{ivar} = value + ::Concurrent::Synchronization.full_memory_barrier + end + RUBY + end + + names.map { |n| [n, :"#{n}="] }.flatten + end + end + end + + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb new file mode 100644 index 0000000000000..019d84382d609 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb @@ -0,0 +1,47 @@ +require 'delegate' +require 'monitor' + +module Concurrent + # This class provides a trivial way to synchronize all calls to a given object + # by wrapping it with a `Delegator` that performs `Monitor#enter/exit` calls + # around the delegated `#send`. Example: + # + # array = [] # not thread-safe on many impls + # array = SynchronizedDelegator.new([]) # thread-safe + # + # A simple `Monitor` provides a very coarse-grained way to synchronize a given + # object, in that it will cause synchronization for methods that have no need + # for it, but this is a trivial way to get thread-safety where none may exist + # currently on some implementations. + # + # This class is currently being considered for inclusion into stdlib, via + # https://bugs.ruby-lang.org/issues/8556 + # + # @!visibility private + class SynchronizedDelegator < SimpleDelegator + def setup + @old_abort = Thread.abort_on_exception + Thread.abort_on_exception = true + end + + def teardown + Thread.abort_on_exception = @old_abort + end + + def initialize(obj) + __setobj__(obj) + @monitor = Monitor.new + end + + def method_missing(method, *args, &block) + monitor = @monitor + begin + monitor.enter + super + ensure + monitor.exit + end + end + + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util.rb new file mode 100644 index 0000000000000..c67084a26fa3a --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util.rb @@ -0,0 +1,16 @@ +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # TODO (pitr-ch 15-Oct-2016): migrate to Utility::NativeInteger + FIXNUM_BIT_SIZE = (0.size * 8) - 2 + MAX_INT = (2 ** FIXNUM_BIT_SIZE) - 1 + # TODO (pitr-ch 15-Oct-2016): migrate to Utility::ProcessorCounter + CPU_COUNT = 16 # is there a way to determine this? + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb new file mode 100644 index 0000000000000..7a6e8d5c0e132 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb @@ -0,0 +1,74 @@ +require 'concurrent/thread_safe/util' +require 'concurrent/thread_safe/util/striped64' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # A Ruby port of the Doug Lea's jsr166e.LondAdder class version 1.8 + # available in public domain. + # + # Original source code available here: + # http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.8 + # + # One or more variables that together maintain an initially zero + # sum. When updates (method +add+) are contended across threads, + # the set of variables may grow dynamically to reduce contention. + # Method +sum+ returns the current total combined across the + # variables maintaining the sum. + # + # This class is usually preferable to single +Atomic+ reference when + # multiple threads update a common sum that is used for purposes such + # as collecting statistics, not for fine-grained synchronization + # control. Under low update contention, the two classes have similar + # characteristics. But under high contention, expected throughput of + # this class is significantly higher, at the expense of higher space + # consumption. + # + # @!visibility private + class Adder < Striped64 + # Adds the given value. + def add(x) + if (current_cells = cells) || !cas_base_computed {|current_base| current_base + x} + was_uncontended = true + hash = hash_code + unless current_cells && (cell = current_cells.volatile_get_by_hash(hash)) && (was_uncontended = cell.cas_computed {|current_value| current_value + x}) + retry_update(x, hash, was_uncontended) {|current_value| current_value + x} + end + end + end + + def increment + add(1) + end + + def decrement + add(-1) + end + + # Returns the current sum. The returned value is _NOT_ an + # atomic snapshot: Invocation in the absence of concurrent + # updates returns an accurate result, but concurrent updates that + # occur while the sum is being calculated might not be + # incorporated. + def sum + x = base + if current_cells = cells + current_cells.each do |cell| + x += cell.value if cell + end + end + x + end + + def reset + internal_reset(0) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb new file mode 100644 index 0000000000000..01eb98f4aa603 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb @@ -0,0 +1,52 @@ +require 'concurrent/thread_safe/util' +require 'concurrent/utility/engine' + +# Shim for TruffleRuby.synchronized +if Concurrent.on_truffleruby? && !TruffleRuby.respond_to?(:synchronized) + module TruffleRuby + def self.synchronized(object, &block) + Truffle::System.synchronized(object, &block) + end + end +end + +module Concurrent + module ThreadSafe + module Util + def self.make_synchronized_on_cruby(klass) + klass.class_eval do + def initialize(*args, &block) + @_monitor = Monitor.new + super + end + + def initialize_copy(other) + # make sure a copy is not sharing a monitor with the original object! + @_monitor = Monitor.new + super + end + end + + klass.superclass.instance_methods(false).each do |method| + klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(*args) + monitor = @_monitor + monitor or raise("BUG: Internal monitor was not properly initialized. Please report this to the concurrent-ruby developers.") + monitor.synchronize { super } + end + RUBY + end + end + + def self.make_synchronized_on_truffleruby(klass) + klass.superclass.instance_methods(false).each do |method| + klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(*args, &block) + TruffleRuby.synchronized(self) { super(*args, &block) } + end + RUBY + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb new file mode 100644 index 0000000000000..b54be39c4cc84 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb @@ -0,0 +1,38 @@ +require 'concurrent/thread_safe/util' +require 'concurrent/tuple' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # @!visibility private + class PowerOfTwoTuple < Concurrent::Tuple + + def initialize(size) + raise ArgumentError, "size must be a power of 2 (#{size.inspect} provided)" unless size > 0 && size & (size - 1) == 0 + super(size) + end + + def hash_to_index(hash) + (size - 1) & hash + end + + def volatile_get_by_hash(hash) + volatile_get(hash_to_index(hash)) + end + + def volatile_set_by_hash(hash, value) + volatile_set(hash_to_index(hash), value) + end + + def next_in_size_table + self.class.new(size << 1) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb new file mode 100644 index 0000000000000..4169c3d36607b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb @@ -0,0 +1,246 @@ +require 'concurrent/thread_safe/util' +require 'concurrent/thread_safe/util/power_of_two_tuple' +require 'concurrent/thread_safe/util/volatile' +require 'concurrent/thread_safe/util/xor_shift_random' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # A Ruby port of the Doug Lea's jsr166e.Striped64 class version 1.6 + # available in public domain. + # + # Original source code available here: + # http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.6 + # + # Class holding common representation and mechanics for classes supporting + # dynamic striping on 64bit values. + # + # This class maintains a lazily-initialized table of atomically updated + # variables, plus an extra +base+ field. The table size is a power of two. + # Indexing uses masked per-thread hash codes. Nearly all methods on this + # class are private, accessed directly by subclasses. + # + # Table entries are of class +Cell+; a variant of AtomicLong padded to + # reduce cache contention on most processors. Padding is overkill for most + # Atomics because they are usually irregularly scattered in memory and thus + # don't interfere much with each other. But Atomic objects residing in + # arrays will tend to be placed adjacent to each other, and so will most + # often share cache lines (with a huge negative performance impact) without + # this precaution. + # + # In part because +Cell+s are relatively large, we avoid creating them until + # they are needed. When there is no contention, all updates are made to the + # +base+ field. Upon first contention (a failed CAS on +base+ update), the + # table is initialized to size 2. The table size is doubled upon further + # contention until reaching the nearest power of two greater than or equal + # to the number of CPUS. Table slots remain empty (+nil+) until they are + # needed. + # + # A single spinlock (+busy+) is used for initializing and resizing the + # table, as well as populating slots with new +Cell+s. There is no need for + # a blocking lock: When the lock is not available, threads try other slots + # (or the base). During these retries, there is increased contention and + # reduced locality, which is still better than alternatives. + # + # Per-thread hash codes are initialized to random values. Contention and/or + # table collisions are indicated by failed CASes when performing an update + # operation (see method +retry_update+). Upon a collision, if the table size + # is less than the capacity, it is doubled in size unless some other thread + # holds the lock. If a hashed slot is empty, and lock is available, a new + # +Cell+ is created. Otherwise, if the slot exists, a CAS is tried. Retries + # proceed by "double hashing", using a secondary hash (XorShift) to try to + # find a free slot. + # + # The table size is capped because, when there are more threads than CPUs, + # supposing that each thread were bound to a CPU, there would exist a + # perfect hash function mapping threads to slots that eliminates collisions. + # When we reach capacity, we search for this mapping by randomly varying the + # hash codes of colliding threads. Because search is random, and collisions + # only become known via CAS failures, convergence can be slow, and because + # threads are typically not bound to CPUS forever, may not occur at all. + # However, despite these limitations, observed contention rates are + # typically low in these cases. + # + # It is possible for a +Cell+ to become unused when threads that once hashed + # to it terminate, as well as in the case where doubling the table causes no + # thread to hash to it under expanded mask. We do not try to detect or + # remove such cells, under the assumption that for long-running instances, + # observed contention levels will recur, so the cells will eventually be + # needed again; and for short-lived ones, it does not matter. + # + # @!visibility private + class Striped64 + + # Padded variant of AtomicLong supporting only raw accesses plus CAS. + # The +value+ field is placed between pads, hoping that the JVM doesn't + # reorder them. + # + # Optimisation note: It would be possible to use a release-only + # form of CAS here, if it were provided. + # + # @!visibility private + class Cell < Concurrent::AtomicReference + + alias_method :cas, :compare_and_set + + def cas_computed + cas(current_value = value, yield(current_value)) + end + + # @!visibility private + def self.padding + # TODO: this only adds padding after the :value slot, need to find a way to add padding before the slot + # TODO (pitr-ch 28-Jul-2018): the padding instance vars may not be created + # hide from yardoc in a method + attr_reader :padding_0, :padding_1, :padding_2, :padding_3, :padding_4, :padding_5, :padding_6, :padding_7, :padding_8, :padding_9, :padding_10, :padding_11 + end + padding + end + + extend Volatile + attr_volatile :cells, # Table of cells. When non-null, size is a power of 2. + :base, # Base value, used mainly when there is no contention, but also as a fallback during table initialization races. Updated via CAS. + :busy # Spinlock (locked via CAS) used when resizing and/or creating Cells. + + alias_method :busy?, :busy + + def initialize + super() + self.busy = false + self.base = 0 + end + + # Handles cases of updates involving initialization, resizing, + # creating new Cells, and/or contention. See above for + # explanation. This method suffers the usual non-modularity + # problems of optimistic retry code, relying on rechecked sets of + # reads. + # + # Arguments: + # [+x+] + # the value + # [+hash_code+] + # hash code used + # [+x+] + # false if CAS failed before call + def retry_update(x, hash_code, was_uncontended) # :yields: current_value + hash = hash_code + collided = false # True if last slot nonempty + while true + if current_cells = cells + if !(cell = current_cells.volatile_get_by_hash(hash)) + if busy? + collided = false + else # Try to attach new Cell + if try_to_install_new_cell(Cell.new(x), hash) # Optimistically create and try to insert new cell + break + else + redo # Slot is now non-empty + end + end + elsif !was_uncontended # CAS already known to fail + was_uncontended = true # Continue after rehash + elsif cell.cas_computed {|current_value| yield current_value} + break + elsif current_cells.size >= CPU_COUNT || cells != current_cells # At max size or stale + collided = false + elsif collided && expand_table_unless_stale(current_cells) + collided = false + redo # Retry with expanded table + else + collided = true + end + hash = XorShiftRandom.xorshift(hash) + + elsif try_initialize_cells(x, hash) || cas_base_computed {|current_base| yield current_base} + break + end + end + self.hash_code = hash + end + + private + # Static per-thread hash code key. Shared across all instances to + # reduce Thread locals pollution and because adjustments due to + # collisions in one table are likely to be appropriate for + # others. + THREAD_LOCAL_KEY = "#{name}.hash_code".to_sym + + # A thread-local hash code accessor. The code is initially + # random, but may be set to a different value upon collisions. + def hash_code + Thread.current[THREAD_LOCAL_KEY] ||= XorShiftRandom.get + end + + def hash_code=(hash) + Thread.current[THREAD_LOCAL_KEY] = hash + end + + # Sets base and all +cells+ to the given value. + def internal_reset(initial_value) + current_cells = cells + self.base = initial_value + if current_cells + current_cells.each do |cell| + cell.value = initial_value if cell + end + end + end + + def cas_base_computed + cas_base(current_base = base, yield(current_base)) + end + + def free? + !busy? + end + + def try_initialize_cells(x, hash) + if free? && !cells + try_in_busy do + unless cells # Recheck under lock + new_cells = PowerOfTwoTuple.new(2) + new_cells.volatile_set_by_hash(hash, Cell.new(x)) + self.cells = new_cells + end + end + end + end + + def expand_table_unless_stale(current_cells) + try_in_busy do + if current_cells == cells # Recheck under lock + new_cells = current_cells.next_in_size_table + current_cells.each_with_index {|x, i| new_cells.volatile_set(i, x)} + self.cells = new_cells + end + end + end + + def try_to_install_new_cell(new_cell, hash) + try_in_busy do + # Recheck under lock + if (current_cells = cells) && !current_cells.volatile_get(i = current_cells.hash_to_index(hash)) + current_cells.volatile_set(i, new_cell) + end + end + end + + def try_in_busy + if cas_busy(false, true) + begin + yield + ensure + self.busy = false + end + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb new file mode 100644 index 0000000000000..cdac2a396a791 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb @@ -0,0 +1,75 @@ +require 'concurrent/thread_safe/util' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # @!visibility private + module Volatile + + # Provides +volatile+ (in the JVM's sense) attribute accessors implemented + # atop of +Concurrent::AtomicReference+. + # + # Usage: + # class Foo + # extend Concurrent::ThreadSafe::Util::Volatile + # attr_volatile :foo, :bar + # + # def initialize(bar) + # super() # must super() into parent initializers before using the volatile attribute accessors + # self.bar = bar + # end + # + # def hello + # my_foo = foo # volatile read + # self.foo = 1 # volatile write + # cas_foo(1, 2) # => true | a strong CAS + # end + # end + def attr_volatile(*attr_names) + return if attr_names.empty? + include(Module.new do + atomic_ref_setup = attr_names.map {|attr_name| "@__#{attr_name} = Concurrent::AtomicReference.new"} + initialize_copy_setup = attr_names.zip(atomic_ref_setup).map do |attr_name, ref_setup| + "#{ref_setup}(other.instance_variable_get(:@__#{attr_name}).get)" + end + class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def initialize(*) + super + #{atomic_ref_setup.join('; ')} + end + + def initialize_copy(other) + super + #{initialize_copy_setup.join('; ')} + end + RUBY_EVAL + + attr_names.each do |attr_name| + class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def #{attr_name} + @__#{attr_name}.get + end + + def #{attr_name}=(value) + @__#{attr_name}.set(value) + end + + def compare_and_set_#{attr_name}(old_value, new_value) + @__#{attr_name}.compare_and_set(old_value, new_value) + end + RUBY_EVAL + + alias_method :"cas_#{attr_name}", :"compare_and_set_#{attr_name}" + alias_method :"lazy_set_#{attr_name}", :"#{attr_name}=" + end + end) + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb new file mode 100644 index 0000000000000..bdde2dd8b363f --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb @@ -0,0 +1,50 @@ +require 'concurrent/thread_safe/util' + +module Concurrent + + # @!visibility private + module ThreadSafe + + # @!visibility private + module Util + + # A xorshift random number (positive +Fixnum+s) generator, provides + # reasonably cheap way to generate thread local random numbers without + # contending for the global +Kernel.rand+. + # + # Usage: + # x = XorShiftRandom.get # uses Kernel.rand to generate an initial seed + # while true + # if (x = XorShiftRandom.xorshift).odd? # thread-localy generate a next random number + # do_something_at_random + # end + # end + module XorShiftRandom + extend self + MAX_XOR_SHIFTABLE_INT = MAX_INT - 1 + + # Generates an initial non-zero positive +Fixnum+ via +Kernel.rand+. + def get + Kernel.rand(MAX_XOR_SHIFTABLE_INT) + 1 # 0 can't be xorshifted + end + + # xorshift based on: http://www.jstatsoft.org/v08/i14/paper + if 0.size == 4 + # using the "yˆ=y>>a; yˆ=y<>c;" transform with the (a,b,c) tuple with values (3,1,14) to minimise Bignum overflows + def xorshift(x) + x ^= x >> 3 + x ^= (x << 1) & MAX_INT # cut-off Bignum overflow + x ^= x >> 14 + end + else + # using the "yˆ=y>>a; yˆ=y<>c;" transform with the (a,b,c) tuple with values (1,1,54) to minimise Bignum overflows + def xorshift(x) + x ^= x >> 1 + x ^= (x << 1) & MAX_INT # cut-off Bignum overflow + x ^= x >> 54 + end + end + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/timer_task.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/timer_task.rb new file mode 100644 index 0000000000000..dd2037f62a107 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/timer_task.rb @@ -0,0 +1,361 @@ +require 'concurrent/collection/copy_on_notify_observer_set' +require 'concurrent/concern/dereferenceable' +require 'concurrent/concern/observable' +require 'concurrent/atomic/atomic_boolean' +require 'concurrent/executor/executor_service' +require 'concurrent/executor/ruby_executor_service' +require 'concurrent/executor/safe_task_executor' +require 'concurrent/scheduled_task' + +module Concurrent + + # A very common concurrency pattern is to run a thread that performs a task at + # regular intervals. The thread that performs the task sleeps for the given + # interval then wakes up and performs the task. Lather, rinse, repeat... This + # pattern causes two problems. First, it is difficult to test the business + # logic of the task because the task itself is tightly coupled with the + # concurrency logic. Second, an exception raised while performing the task can + # cause the entire thread to abend. In a long-running application where the + # task thread is intended to run for days/weeks/years a crashed task thread + # can pose a significant problem. `TimerTask` alleviates both problems. + # + # When a `TimerTask` is launched it starts a thread for monitoring the + # execution interval. The `TimerTask` thread does not perform the task, + # however. Instead, the TimerTask launches the task on a separate thread. + # Should the task experience an unrecoverable crash only the task thread will + # crash. This makes the `TimerTask` very fault tolerant. Additionally, the + # `TimerTask` thread can respond to the success or failure of the task, + # performing logging or ancillary operations. + # + # One other advantage of `TimerTask` is that it forces the business logic to + # be completely decoupled from the concurrency logic. The business logic can + # be tested separately then passed to the `TimerTask` for scheduling and + # running. + # + # A `TimerTask` supports two different types of interval calculations. + # A fixed delay will always wait the same amount of time between the + # completion of one task and the start of the next. A fixed rate will + # attempt to maintain a constant rate of execution regardless of the + # duration of the task. For example, if a fixed rate task is scheduled + # to run every 60 seconds but the task itself takes 10 seconds to + # complete, the next task will be scheduled to run 50 seconds after + # the start of the previous task. If the task takes 70 seconds to + # complete, the next task will be start immediately after the previous + # task completes. Tasks will not be executed concurrently. + # + # In some cases it may be necessary for a `TimerTask` to affect its own + # execution cycle. To facilitate this, a reference to the TimerTask instance + # is passed as an argument to the provided block every time the task is + # executed. + # + # The `TimerTask` class includes the `Dereferenceable` mixin module so the + # result of the last execution is always available via the `#value` method. + # Dereferencing options can be passed to the `TimerTask` during construction or + # at any later time using the `#set_deref_options` method. + # + # `TimerTask` supports notification through the Ruby standard library + # {http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html + # Observable} module. On execution the `TimerTask` will notify the observers + # with three arguments: time of execution, the result of the block (or nil on + # failure), and any raised exceptions (or nil on success). + # + # @!macro copy_options + # + # @example Basic usage + # task = Concurrent::TimerTask.new{ puts 'Boom!' } + # task.execute + # + # task.execution_interval #=> 60 (default) + # + # # wait 60 seconds... + # #=> 'Boom!' + # + # task.shutdown #=> true + # + # @example Configuring `:execution_interval` + # task = Concurrent::TimerTask.new(execution_interval: 5) do + # puts 'Boom!' + # end + # + # task.execution_interval #=> 5 + # + # @example Immediate execution with `:run_now` + # task = Concurrent::TimerTask.new(run_now: true){ puts 'Boom!' } + # task.execute + # + # #=> 'Boom!' + # + # @example Configuring `:interval_type` with either :fixed_delay or :fixed_rate, default is :fixed_delay + # task = Concurrent::TimerTask.new(execution_interval: 5, interval_type: :fixed_rate) do + # puts 'Boom!' + # end + # task.interval_type #=> :fixed_rate + # + # @example Last `#value` and `Dereferenceable` mixin + # task = Concurrent::TimerTask.new( + # dup_on_deref: true, + # execution_interval: 5 + # ){ Time.now } + # + # task.execute + # Time.now #=> 2013-11-07 18:06:50 -0500 + # sleep(10) + # task.value #=> 2013-11-07 18:06:55 -0500 + # + # @example Controlling execution from within the block + # timer_task = Concurrent::TimerTask.new(execution_interval: 1) do |task| + # task.execution_interval.to_i.times{ print 'Boom! ' } + # print "\n" + # task.execution_interval += 1 + # if task.execution_interval > 5 + # puts 'Stopping...' + # task.shutdown + # end + # end + # + # timer_task.execute + # #=> Boom! + # #=> Boom! Boom! + # #=> Boom! Boom! Boom! + # #=> Boom! Boom! Boom! Boom! + # #=> Boom! Boom! Boom! Boom! Boom! + # #=> Stopping... + # + # @example Observation + # class TaskObserver + # def update(time, result, ex) + # if result + # print "(#{time}) Execution successfully returned #{result}\n" + # else + # print "(#{time}) Execution failed with error #{ex}\n" + # end + # end + # end + # + # task = Concurrent::TimerTask.new(execution_interval: 1){ 42 } + # task.add_observer(TaskObserver.new) + # task.execute + # sleep 4 + # + # #=> (2013-10-13 19:08:58 -0400) Execution successfully returned 42 + # #=> (2013-10-13 19:08:59 -0400) Execution successfully returned 42 + # #=> (2013-10-13 19:09:00 -0400) Execution successfully returned 42 + # task.shutdown + # + # task = Concurrent::TimerTask.new(execution_interval: 1){ sleep } + # task.add_observer(TaskObserver.new) + # task.execute + # + # #=> (2013-10-13 19:07:25 -0400) Execution timed out + # #=> (2013-10-13 19:07:27 -0400) Execution timed out + # #=> (2013-10-13 19:07:29 -0400) Execution timed out + # task.shutdown + # + # task = Concurrent::TimerTask.new(execution_interval: 1){ raise StandardError } + # task.add_observer(TaskObserver.new) + # task.execute + # + # #=> (2013-10-13 19:09:37 -0400) Execution failed with error StandardError + # #=> (2013-10-13 19:09:38 -0400) Execution failed with error StandardError + # #=> (2013-10-13 19:09:39 -0400) Execution failed with error StandardError + # task.shutdown + # + # @see http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html + # @see http://docs.oracle.com/javase/7/docs/api/java/util/TimerTask.html + class TimerTask < RubyExecutorService + include Concern::Dereferenceable + include Concern::Observable + + # Default `:execution_interval` in seconds. + EXECUTION_INTERVAL = 60 + + # Maintain the interval between the end of one execution and the start of the next execution. + FIXED_DELAY = :fixed_delay + + # Maintain the interval between the start of one execution and the start of the next. + # If execution time exceeds the interval, the next execution will start immediately + # after the previous execution finishes. Executions will not run concurrently. + FIXED_RATE = :fixed_rate + + # Default `:interval_type` + DEFAULT_INTERVAL_TYPE = FIXED_DELAY + + # Create a new TimerTask with the given task and configuration. + # + # @!macro timer_task_initialize + # @param [Hash] opts the options defining task execution. + # @option opts [Float] :execution_interval number of seconds between + # task executions (default: EXECUTION_INTERVAL) + # @option opts [Boolean] :run_now Whether to run the task immediately + # upon instantiation or to wait until the first # execution_interval + # has passed (default: false) + # @options opts [Symbol] :interval_type method to calculate the interval + # between executions, can be either :fixed_rate or :fixed_delay. + # (default: :fixed_delay) + # @option opts [Executor] executor, default is `global_io_executor` + # + # @!macro deref_options + # + # @raise ArgumentError when no block is given. + # + # @yield to the block after :execution_interval seconds have passed since + # the last yield + # @yieldparam task a reference to the `TimerTask` instance so that the + # block can control its own lifecycle. Necessary since `self` will + # refer to the execution context of the block rather than the running + # `TimerTask`. + # + # @return [TimerTask] the new `TimerTask` + def initialize(opts = {}, &task) + raise ArgumentError.new('no block given') unless block_given? + super + set_deref_options opts + end + + # Is the executor running? + # + # @return [Boolean] `true` when running, `false` when shutting down or shutdown + def running? + @running.true? + end + + # Execute a previously created `TimerTask`. + # + # @return [TimerTask] a reference to `self` + # + # @example Instance and execute in separate steps + # task = Concurrent::TimerTask.new(execution_interval: 10){ print "Hello World\n" } + # task.running? #=> false + # task.execute + # task.running? #=> true + # + # @example Instance and execute in one line + # task = Concurrent::TimerTask.new(execution_interval: 10){ print "Hello World\n" }.execute + # task.running? #=> true + def execute + synchronize do + if @running.false? + @running.make_true + schedule_next_task(@run_now ? 0 : @execution_interval) + end + end + self + end + + # Create and execute a new `TimerTask`. + # + # @!macro timer_task_initialize + # + # @example + # task = Concurrent::TimerTask.execute(execution_interval: 10){ print "Hello World\n" } + # task.running? #=> true + def self.execute(opts = {}, &task) + TimerTask.new(opts, &task).execute + end + + # @!attribute [rw] execution_interval + # @return [Fixnum] Number of seconds after the task completes before the + # task is performed again. + def execution_interval + synchronize { @execution_interval } + end + + # @!attribute [rw] execution_interval + # @return [Fixnum] Number of seconds after the task completes before the + # task is performed again. + def execution_interval=(value) + if (value = value.to_f) <= 0.0 + raise ArgumentError.new('must be greater than zero') + else + synchronize { @execution_interval = value } + end + end + + # @!attribute [r] interval_type + # @return [Symbol] method to calculate the interval between executions + attr_reader :interval_type + + # @!attribute [rw] timeout_interval + # @return [Fixnum] Number of seconds the task can run before it is + # considered to have failed. + def timeout_interval + warn 'TimerTask timeouts are now ignored as these were not able to be implemented correctly' + end + + # @!attribute [rw] timeout_interval + # @return [Fixnum] Number of seconds the task can run before it is + # considered to have failed. + def timeout_interval=(value) + warn 'TimerTask timeouts are now ignored as these were not able to be implemented correctly' + end + + private :post, :<< + + private + + def ns_initialize(opts, &task) + set_deref_options(opts) + + self.execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL + if opts[:interval_type] && ![FIXED_DELAY, FIXED_RATE].include?(opts[:interval_type]) + raise ArgumentError.new('interval_type must be either :fixed_delay or :fixed_rate') + end + if opts[:timeout] || opts[:timeout_interval] + warn 'TimeTask timeouts are now ignored as these were not able to be implemented correctly' + end + + @run_now = opts[:now] || opts[:run_now] + @interval_type = opts[:interval_type] || DEFAULT_INTERVAL_TYPE + @task = Concurrent::SafeTaskExecutor.new(task) + @executor = opts[:executor] || Concurrent.global_io_executor + @running = Concurrent::AtomicBoolean.new(false) + @value = nil + + self.observers = Collection::CopyOnNotifyObserverSet.new + end + + # @!visibility private + def ns_shutdown_execution + @running.make_false + super + end + + # @!visibility private + def ns_kill_execution + @running.make_false + super + end + + # @!visibility private + def schedule_next_task(interval = execution_interval) + ScheduledTask.execute(interval, executor: @executor, args: [Concurrent::Event.new], &method(:execute_task)) + nil + end + + # @!visibility private + def execute_task(completion) + return nil unless @running.true? + start_time = Concurrent.monotonic_time + _success, value, reason = @task.execute(self) + if completion.try? + self.value = value + schedule_next_task(calculate_next_interval(start_time)) + time = Time.now + observers.notify_observers do + [time, self.value, reason] + end + end + nil + end + + # @!visibility private + def calculate_next_interval(start_time) + if @interval_type == FIXED_RATE + run_time = Concurrent.monotonic_time - start_time + [execution_interval - run_time, 0].max + else # FIXED_DELAY + execution_interval + end + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tuple.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tuple.rb new file mode 100644 index 0000000000000..56212cfd15cc6 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tuple.rb @@ -0,0 +1,82 @@ +require 'concurrent/atomic/atomic_reference' + +module Concurrent + + # A fixed size array with volatile (synchronized, thread safe) getters/setters. + # Mixes in Ruby's `Enumerable` module for enhanced search, sort, and traversal. + # + # @example + # tuple = Concurrent::Tuple.new(16) + # + # tuple.set(0, :foo) #=> :foo | volatile write + # tuple.get(0) #=> :foo | volatile read + # tuple.compare_and_set(0, :foo, :bar) #=> true | strong CAS + # tuple.cas(0, :foo, :baz) #=> false | strong CAS + # tuple.get(0) #=> :bar | volatile read + # + # @see https://en.wikipedia.org/wiki/Tuple Tuple entry at Wikipedia + # @see http://www.erlang.org/doc/reference_manual/data_types.html#id70396 Erlang Tuple + # @see http://ruby-doc.org/core-2.2.2/Enumerable.html Enumerable + class Tuple + include Enumerable + + # The (fixed) size of the tuple. + attr_reader :size + + # Create a new tuple of the given size. + # + # @param [Integer] size the number of elements in the tuple + def initialize(size) + @size = size + @tuple = tuple = ::Array.new(size) + i = 0 + while i < size + tuple[i] = Concurrent::AtomicReference.new + i += 1 + end + end + + # Get the value of the element at the given index. + # + # @param [Integer] i the index from which to retrieve the value + # @return [Object] the value at the given index or nil if the index is out of bounds + def get(i) + return nil if i >= @size || i < 0 + @tuple[i].get + end + alias_method :volatile_get, :get + + # Set the element at the given index to the given value + # + # @param [Integer] i the index for the element to set + # @param [Object] value the value to set at the given index + # + # @return [Object] the new value of the element at the given index or nil if the index is out of bounds + def set(i, value) + return nil if i >= @size || i < 0 + @tuple[i].set(value) + end + alias_method :volatile_set, :set + + # Set the value at the given index to the new value if and only if the current + # value matches the given old value. + # + # @param [Integer] i the index for the element to set + # @param [Object] old_value the value to compare against the current value + # @param [Object] new_value the value to set at the given index + # + # @return [Boolean] true if the value at the given element was set else false + def compare_and_set(i, old_value, new_value) + return false if i >= @size || i < 0 + @tuple[i].compare_and_set(old_value, new_value) + end + alias_method :cas, :compare_and_set + + # Calls the given block once for each element in self, passing that element as a parameter. + # + # @yieldparam [Object] ref the `Concurrent::AtomicReference` object at the current index + def each + @tuple.each {|ref| yield ref.get} + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tvar.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tvar.rb new file mode 100644 index 0000000000000..5d02ef090fd0c --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/tvar.rb @@ -0,0 +1,222 @@ +require 'set' +require 'concurrent/synchronization/object' + +module Concurrent + + # A `TVar` is a transactional variable - a single-element container that + # is used as part of a transaction - see `Concurrent::atomically`. + # + # @!macro thread_safe_variable_comparison + # + # {include:file:docs-source/tvar.md} + class TVar < Synchronization::Object + safe_initialization! + + # Create a new `TVar` with an initial value. + def initialize(value) + @value = value + @lock = Mutex.new + end + + # Get the value of a `TVar`. + def value + Concurrent::atomically do + Transaction::current.read(self) + end + end + + # Set the value of a `TVar`. + def value=(value) + Concurrent::atomically do + Transaction::current.write(self, value) + end + end + + # @!visibility private + def unsafe_value # :nodoc: + @value + end + + # @!visibility private + def unsafe_value=(value) # :nodoc: + @value = value + end + + # @!visibility private + def unsafe_lock # :nodoc: + @lock + end + + end + + # Run a block that reads and writes `TVar`s as a single atomic transaction. + # With respect to the value of `TVar` objects, the transaction is atomic, in + # that it either happens or it does not, consistent, in that the `TVar` + # objects involved will never enter an illegal state, and isolated, in that + # transactions never interfere with each other. You may recognise these + # properties from database transactions. + # + # There are some very important and unusual semantics that you must be aware of: + # + # * Most importantly, the block that you pass to atomically may be executed + # more than once. In most cases your code should be free of + # side-effects, except for via TVar. + # + # * If an exception escapes an atomically block it will abort the transaction. + # + # * It is undefined behaviour to use callcc or Fiber with atomically. + # + # * If you create a new thread within an atomically, it will not be part of + # the transaction. Creating a thread counts as a side-effect. + # + # Transactions within transactions are flattened to a single transaction. + # + # @example + # a = new TVar(100_000) + # b = new TVar(100) + # + # Concurrent::atomically do + # a.value -= 10 + # b.value += 10 + # end + def atomically + raise ArgumentError.new('no block given') unless block_given? + + # Get the current transaction + + transaction = Transaction::current + + # Are we not already in a transaction (not nested)? + + if transaction.nil? + # New transaction + + begin + # Retry loop + + loop do + + # Create a new transaction + + transaction = Transaction.new + Transaction::current = transaction + + # Run the block, aborting on exceptions + + begin + result = yield + rescue Transaction::AbortError => e + transaction.abort + result = Transaction::ABORTED + rescue Transaction::LeaveError => e + transaction.abort + break result + rescue => e + transaction.abort + raise e + end + # If we can commit, break out of the loop + + if result != Transaction::ABORTED + if transaction.commit + break result + end + end + end + ensure + # Clear the current transaction + + Transaction::current = nil + end + else + # Nested transaction - flatten it and just run the block + + yield + end + end + + # Abort a currently running transaction - see `Concurrent::atomically`. + def abort_transaction + raise Transaction::AbortError.new + end + + # Leave a transaction without committing or aborting - see `Concurrent::atomically`. + def leave_transaction + raise Transaction::LeaveError.new + end + + module_function :atomically, :abort_transaction, :leave_transaction + + private + + # @!visibility private + class Transaction + + ABORTED = ::Object.new + + OpenEntry = Struct.new(:value, :modified) + + AbortError = Class.new(StandardError) + LeaveError = Class.new(StandardError) + + def initialize + @open_tvars = {} + end + + def read(tvar) + entry = open(tvar) + entry.value + end + + def write(tvar, value) + entry = open(tvar) + entry.modified = true + entry.value = value + end + + def open(tvar) + entry = @open_tvars[tvar] + + unless entry + unless tvar.unsafe_lock.try_lock + Concurrent::abort_transaction + end + + entry = OpenEntry.new(tvar.unsafe_value, false) + @open_tvars[tvar] = entry + end + + entry + end + + def abort + unlock + end + + def commit + @open_tvars.each do |tvar, entry| + if entry.modified + tvar.unsafe_value = entry.value + end + end + + unlock + end + + def unlock + @open_tvars.each_key do |tvar| + tvar.unsafe_lock.unlock + end + end + + def self.current + Thread.current[:current_tvar_transaction] + end + + def self.current=(transaction) + Thread.current[:current_tvar_transaction] = transaction + end + + end + +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/engine.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/engine.rb new file mode 100644 index 0000000000000..0c574b2abb893 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/engine.rb @@ -0,0 +1,45 @@ +module Concurrent + # @!visibility private + module Utility + + # @!visibility private + module EngineDetector + def on_cruby? + RUBY_ENGINE == 'ruby' + end + + def on_jruby? + RUBY_ENGINE == 'jruby' + end + + def on_truffleruby? + RUBY_ENGINE == 'truffleruby' + end + + def on_windows? + !(RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/).nil? + end + + def on_osx? + !(RbConfig::CONFIG['host_os'] =~ /darwin|mac os/).nil? + end + + def on_linux? + !(RbConfig::CONFIG['host_os'] =~ /linux/).nil? + end + + def ruby_version(version = RUBY_VERSION, comparison, major, minor, patch) + result = (version.split('.').map(&:to_i) <=> [major, minor, patch]) + comparisons = { :== => [0], + :>= => [1, 0], + :<= => [-1, 0], + :> => [1], + :< => [-1] } + comparisons.fetch(comparison).include? result + end + end + end + + # @!visibility private + extend Utility::EngineDetector +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb new file mode 100644 index 0000000000000..1c987d8a411fc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb @@ -0,0 +1,19 @@ +module Concurrent + + # @!macro monotonic_get_time + # + # Returns the current time as tracked by the application monotonic clock. + # + # @param [Symbol] unit the time unit to be returned, can be either + # :float_second, :float_millisecond, :float_microsecond, :second, + # :millisecond, :microsecond, or :nanosecond default to :float_second. + # + # @return [Float] The current monotonic time since some unspecified + # starting point + # + # @!macro monotonic_clock_warning + def monotonic_time(unit = :float_second) + Process.clock_gettime(Process::CLOCK_MONOTONIC, unit) + end + module_function :monotonic_time +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb new file mode 100644 index 0000000000000..bf7bab354e832 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb @@ -0,0 +1,77 @@ +require 'concurrent/utility/engine' +# Synchronization::AbstractObject must be defined before loading the extension +require 'concurrent/synchronization/abstract_object' + +module Concurrent + # @!visibility private + module Utility + # @!visibility private + module NativeExtensionLoader + + def allow_c_extensions? + Concurrent.on_cruby? + end + + def c_extensions_loaded? + defined?(@c_extensions_loaded) && @c_extensions_loaded + end + + def load_native_extensions + if Concurrent.on_cruby? && !c_extensions_loaded? + ['concurrent/concurrent_ruby_ext', + "concurrent/#{RUBY_VERSION[0..2]}/concurrent_ruby_ext" + ].each { |p| try_load_c_extension p } + end + + if Concurrent.on_jruby? && !java_extensions_loaded? + begin + require 'concurrent/concurrent_ruby.jar' + set_java_extensions_loaded + rescue LoadError => e + raise e, "Java extensions are required for JRuby.\n" + e.message, e.backtrace + end + end + end + + private + + def load_error_path(error) + if error.respond_to? :path + error.path + else + error.message.split(' -- ').last + end + end + + def set_c_extensions_loaded + @c_extensions_loaded = true + end + + def java_extensions_loaded? + defined?(@java_extensions_loaded) && @java_extensions_loaded + end + + def set_java_extensions_loaded + @java_extensions_loaded = true + end + + def try_load_c_extension(path) + require path + set_c_extensions_loaded + rescue LoadError => e + if load_error_path(e) == path + # move on with pure-Ruby implementations + # TODO (pitr-ch 12-Jul-2018): warning on verbose? + else + raise e + end + end + + end + end + + # @!visibility private + extend Utility::NativeExtensionLoader +end + +Concurrent.load_native_extensions diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_integer.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_integer.rb new file mode 100644 index 0000000000000..de1cdc306a1bd --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/native_integer.rb @@ -0,0 +1,54 @@ +module Concurrent + # @!visibility private + module Utility + # @private + module NativeInteger + # http://stackoverflow.com/questions/535721/ruby-max-integer + MIN_VALUE = -(2**(0.size * 8 - 2)) + MAX_VALUE = (2**(0.size * 8 - 2) - 1) + + def ensure_upper_bound(value) + if value > MAX_VALUE + raise RangeError.new("#{value} is greater than the maximum value of #{MAX_VALUE}") + end + value + end + + def ensure_lower_bound(value) + if value < MIN_VALUE + raise RangeError.new("#{value} is less than the maximum value of #{MIN_VALUE}") + end + value + end + + def ensure_integer(value) + unless value.is_a?(Integer) + raise ArgumentError.new("#{value} is not an Integer") + end + value + end + + def ensure_integer_and_bounds(value) + ensure_integer value + ensure_upper_bound value + ensure_lower_bound value + end + + def ensure_positive(value) + if value < 0 + raise ArgumentError.new("#{value} cannot be negative") + end + value + end + + def ensure_positive_and_no_zero(value) + if value < 1 + raise ArgumentError.new("#{value} cannot be negative or zero") + end + value + end + + extend self + end + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/processor_counter.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/processor_counter.rb new file mode 100644 index 0000000000000..2489cbd76b1de --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/utility/processor_counter.rb @@ -0,0 +1,220 @@ +require 'etc' +require 'rbconfig' +require 'concurrent/delay' + +module Concurrent + # @!visibility private + module Utility + + # @!visibility private + class ProcessorCounter + def initialize + @processor_count = Delay.new { compute_processor_count } + @physical_processor_count = Delay.new { compute_physical_processor_count } + @cpu_quota = Delay.new { compute_cpu_quota } + @cpu_shares = Delay.new { compute_cpu_shares } + end + + def processor_count + @processor_count.value + end + + def physical_processor_count + @physical_processor_count.value + end + + def available_processor_count + cpu_count = processor_count.to_f + quota = cpu_quota + + return cpu_count if quota.nil? + + # cgroup cpus quotas have no limits, so they can be set to higher than the + # real count of cores. + if quota > cpu_count + cpu_count + else + quota + end + end + + def cpu_quota + @cpu_quota.value + end + + def cpu_shares + @cpu_shares.value + end + + private + + def compute_processor_count + if Concurrent.on_jruby? + java.lang.Runtime.getRuntime.availableProcessors + else + Etc.nprocessors + end + end + + def compute_physical_processor_count + ppc = case RbConfig::CONFIG["target_os"] + when /darwin\d\d/ + IO.popen("/usr/sbin/sysctl -n hw.physicalcpu", &:read).to_i + when /linux/ + cores = {} # unique physical ID / core ID combinations + phy = 0 + IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln| + if ln.start_with?("physical") + phy = ln[/\d+/] + elsif ln.start_with?("core") + cid = phy + ":" + ln[/\d+/] + cores[cid] = true if not cores[cid] + end + end + cores.count + when /mswin|mingw/ + # Get-CimInstance introduced in PowerShell 3 or earlier: https://learn.microsoft.com/en-us/previous-versions/powershell/module/cimcmdlets/get-ciminstance?view=powershell-3.0 + result = run('powershell -command "Get-CimInstance -ClassName Win32_Processor -Property NumberOfCores | Select-Object -Property NumberOfCores"') + if !result || $?.exitstatus != 0 + # fallback to deprecated wmic for older systems + result = run("wmic cpu get NumberOfCores") + end + if !result || $?.exitstatus != 0 + # Bail out if both commands returned something unexpected + processor_count + else + # powershell: "\nNumberOfCores\n-------------\n 4\n\n\n" + # wmic: "NumberOfCores \n\n4 \n\n\n\n" + result.scan(/\d+/).map(&:to_i).reduce(:+) + end + else + processor_count + end + # fall back to logical count if physical info is invalid + ppc > 0 ? ppc : processor_count + rescue + return 1 + end + + def run(command) + IO.popen(command, &:read) + rescue Errno::ENOENT + end + + def compute_cpu_quota + if RbConfig::CONFIG["target_os"].include?("linux") + if File.exist?("/sys/fs/cgroup/cpu.max") + # cgroups v2: https://docs.kernel.org/admin-guide/cgroup-v2.html#cpu-interface-files + cpu_max = File.read("/sys/fs/cgroup/cpu.max") + return nil if cpu_max.start_with?("max ") # no limit + max, period = cpu_max.split.map(&:to_f) + max / period + elsif File.exist?("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us") + # cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt + max = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us").to_i + # If the cpu.cfs_quota_us is -1, cgroup does not adhere to any CPU time restrictions + # https://docs.kernel.org/scheduler/sched-bwc.html#management + return nil if max <= 0 + period = File.read("/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us").to_f + max / period + end + end + end + + def compute_cpu_shares + if RbConfig::CONFIG["target_os"].include?("linux") + if File.exist?("/sys/fs/cgroup/cpu.weight") + # cgroups v2: https://docs.kernel.org/admin-guide/cgroup-v2.html#cpu-interface-files + # Ref: https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2254-cgroup-v2#phase-1-convert-from-cgroups-v1-settings-to-v2 + weight = File.read("/sys/fs/cgroup/cpu.weight").to_f + ((((weight - 1) * 262142) / 9999) + 2) / 1024 + elsif File.exist?("/sys/fs/cgroup/cpu/cpu.shares") + # cgroups v1: https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt + File.read("/sys/fs/cgroup/cpu/cpu.shares").to_f / 1024 + end + end + end + end + end + + # create the default ProcessorCounter on load + @processor_counter = Utility::ProcessorCounter.new + singleton_class.send :attr_reader, :processor_counter + + # Number of processors seen by the OS and used for process scheduling. For + # performance reasons the calculated value will be memoized on the first + # call. + # + # When running under JRuby the Java runtime call + # `java.lang.Runtime.getRuntime.availableProcessors` will be used. According + # to the Java documentation this "value may change during a particular + # invocation of the virtual machine... [applications] should therefore + # occasionally poll this property." We still memoize this value once under + # JRuby. + # + # Otherwise Ruby's Etc.nprocessors will be used. + # + # @return [Integer] number of processors seen by the OS or Java runtime + # + # @see http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html#availableProcessors() + def self.processor_count + processor_counter.processor_count + end + + # Number of physical processor cores on the current system. For performance + # reasons the calculated value will be memoized on the first call. + # + # On Windows the Win32 API will be queried for the `NumberOfCores from + # Win32_Processor`. This will return the total number "of cores for the + # current instance of the processor." On Unix-like operating systems either + # the `hwprefs` or `sysctl` utility will be called in a subshell and the + # returned value will be used. In the rare case where none of these methods + # work or an exception is raised the function will simply return 1. + # + # @return [Integer] number physical processor cores on the current system + # + # @see https://github.com/grosser/parallel/blob/4fc8b89d08c7091fe0419ca8fba1ec3ce5a8d185/lib/parallel.rb + # + # @see http://msdn.microsoft.com/en-us/library/aa394373(v=vs.85).aspx + # @see http://www.unix.com/man-page/osx/1/HWPREFS/ + # @see http://linux.die.net/man/8/sysctl + def self.physical_processor_count + processor_counter.physical_processor_count + end + + # Number of processors cores available for process scheduling. + # This method takes in account the CPU quota if the process is inside a cgroup with a + # dedicated CPU quota (typically Docker). + # Otherwise it returns the same value as #processor_count but as a Float. + # + # For performance reasons the calculated value will be memoized on the first + # call. + # + # @return [Float] number of available processors + def self.available_processor_count + processor_counter.available_processor_count + end + + # The maximum number of processors cores available for process scheduling. + # Returns `nil` if there is no enforced limit, or a `Float` if the + # process is inside a cgroup with a dedicated CPU quota (typically Docker). + # + # Note that nothing prevents setting a CPU quota higher than the actual number of + # cores on the system. + # + # For performance reasons the calculated value will be memoized on the first + # call. + # + # @return [nil, Float] Maximum number of available processors as set by a cgroup CPU quota, or nil if none set + def self.cpu_quota + processor_counter.cpu_quota + end + + # The CPU shares requested by the process. For performance reasons the calculated + # value will be memoized on the first call. + # + # @return [Float, nil] CPU shares requested by the process, or nil if not set + def self.cpu_shares + processor_counter.cpu_shares + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/version.rb new file mode 100644 index 0000000000000..1b0c4c22f4acb --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/version.rb @@ -0,0 +1,3 @@ +module Concurrent + VERSION = '1.3.4' +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt new file mode 100644 index 0000000000000..bfe58e510bd1e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2016 Jan Lelis, https://janlelis.com + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/cli-spinners.json b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/cli-spinners.json new file mode 100644 index 0000000000000..89b0edba1c483 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/cli-spinners.json @@ -0,0 +1,1415 @@ +{ + "dots": { + "interval": 80, + "frames": [ + "⠋", + "⠙", + "⠹", + "⠸", + "⠼", + "⠴", + "⠦", + "⠧", + "⠇", + "⠏" + ] + }, + "dots2": { + "interval": 80, + "frames": [ + "⣾", + "⣽", + "⣻", + "⢿", + "⡿", + "⣟", + "⣯", + "⣷" + ] + }, + "dots3": { + "interval": 80, + "frames": [ + "⠋", + "⠙", + "⠚", + "⠞", + "⠖", + "⠦", + "⠴", + "⠲", + "⠳", + "⠓" + ] + }, + "dots4": { + "interval": 80, + "frames": [ + "⠄", + "⠆", + "⠇", + "⠋", + "⠙", + "⠸", + "⠰", + "⠠", + "⠰", + "⠸", + "⠙", + "⠋", + "⠇", + "⠆" + ] + }, + "dots5": { + "interval": 80, + "frames": [ + "⠋", + "⠙", + "⠚", + "⠒", + "⠂", + "⠂", + "⠒", + "⠲", + "⠴", + "⠦", + "⠖", + "⠒", + "⠐", + "⠐", + "⠒", + "⠓", + "⠋" + ] + }, + "dots6": { + "interval": 80, + "frames": [ + "⠁", + "⠉", + "⠙", + "⠚", + "⠒", + "⠂", + "⠂", + "⠒", + "⠲", + "⠴", + "⠤", + "⠄", + "⠄", + "⠤", + "⠴", + "⠲", + "⠒", + "⠂", + "⠂", + "⠒", + "⠚", + "⠙", + "⠉", + "⠁" + ] + }, + "dots7": { + "interval": 80, + "frames": [ + "⠈", + "⠉", + "⠋", + "⠓", + "⠒", + "⠐", + "⠐", + "⠒", + "⠖", + "⠦", + "⠤", + "⠠", + "⠠", + "⠤", + "⠦", + "⠖", + "⠒", + "⠐", + "⠐", + "⠒", + "⠓", + "⠋", + "⠉", + "⠈" + ] + }, + "dots8": { + "interval": 80, + "frames": [ + "⠁", + "⠁", + "⠉", + "⠙", + "⠚", + "⠒", + "⠂", + "⠂", + "⠒", + "⠲", + "⠴", + "⠤", + "⠄", + "⠄", + "⠤", + "⠠", + "⠠", + "⠤", + "⠦", + "⠖", + "⠒", + "⠐", + "⠐", + "⠒", + "⠓", + "⠋", + "⠉", + "⠈", + "⠈" + ] + }, + "dots9": { + "interval": 80, + "frames": [ + "⢹", + "⢺", + "⢼", + "⣸", + "⣇", + "⡧", + "⡗", + "⡏" + ] + }, + "dots10": { + "interval": 80, + "frames": [ + "⢄", + "⢂", + "⢁", + "⡁", + "⡈", + "⡐", + "⡠" + ] + }, + "dots11": { + "interval": 100, + "frames": [ + "⠁", + "⠂", + "⠄", + "⡀", + "⢀", + "⠠", + "⠐", + "⠈" + ] + }, + "dots12": { + "interval": 80, + "frames": [ + "⢀⠀", + "⡀⠀", + "⠄⠀", + "⢂⠀", + "⡂⠀", + "⠅⠀", + "⢃⠀", + "⡃⠀", + "⠍⠀", + "⢋⠀", + "⡋⠀", + "⠍⠁", + "⢋⠁", + "⡋⠁", + "⠍⠉", + "⠋⠉", + "⠋⠉", + "⠉⠙", + "⠉⠙", + "⠉⠩", + "⠈⢙", + "⠈⡙", + "⢈⠩", + "⡀⢙", + "⠄⡙", + "⢂⠩", + "⡂⢘", + "⠅⡘", + "⢃⠨", + "⡃⢐", + "⠍⡐", + "⢋⠠", + "⡋⢀", + "⠍⡁", + "⢋⠁", + "⡋⠁", + "⠍⠉", + "⠋⠉", + "⠋⠉", + "⠉⠙", + "⠉⠙", + "⠉⠩", + "⠈⢙", + "⠈⡙", + "⠈⠩", + "⠀⢙", + "⠀⡙", + "⠀⠩", + "⠀⢘", + "⠀⡘", + "⠀⠨", + "⠀⢐", + "⠀⡐", + "⠀⠠", + "⠀⢀", + "⠀⡀" + ] + }, + "dots8Bit": { + "interval": 80, + "frames": [ + "⠀", + "⠁", + "⠂", + "⠃", + "⠄", + "⠅", + "⠆", + "⠇", + "⡀", + "⡁", + "⡂", + "⡃", + "⡄", + "⡅", + "⡆", + "⡇", + "⠈", + "⠉", + "⠊", + "⠋", + "⠌", + "⠍", + "⠎", + "⠏", + "⡈", + "⡉", + "⡊", + "⡋", + "⡌", + "⡍", + "⡎", + "⡏", + "⠐", + "⠑", + "⠒", + "⠓", + "⠔", + "⠕", + "⠖", + "⠗", + "⡐", + "⡑", + "⡒", + "⡓", + "⡔", + "⡕", + "⡖", + "⡗", + "⠘", + "⠙", + "⠚", + "⠛", + "⠜", + "⠝", + "⠞", + "⠟", + "⡘", + "⡙", + "⡚", + "⡛", + "⡜", + "⡝", + "⡞", + "⡟", + "⠠", + "⠡", + "⠢", + "⠣", + "⠤", + "⠥", + "⠦", + "⠧", + "⡠", + "⡡", + "⡢", + "⡣", + "⡤", + "⡥", + "⡦", + "⡧", + "⠨", + "⠩", + "⠪", + "⠫", + "⠬", + "⠭", + "⠮", + "⠯", + "⡨", + "⡩", + "⡪", + "⡫", + "⡬", + "⡭", + "⡮", + "⡯", + "⠰", + "⠱", + "⠲", + "⠳", + "⠴", + "⠵", + "⠶", + "⠷", + "⡰", + "⡱", + "⡲", + "⡳", + "⡴", + "⡵", + "⡶", + "⡷", + "⠸", + "⠹", + "⠺", + "⠻", + "⠼", + "⠽", + "⠾", + "⠿", + "⡸", + "⡹", + "⡺", + "⡻", + "⡼", + "⡽", + "⡾", + "⡿", + "⢀", + "⢁", + "⢂", + "⢃", + "⢄", + "⢅", + "⢆", + "⢇", + "⣀", + "⣁", + "⣂", + "⣃", + "⣄", + "⣅", + "⣆", + "⣇", + "⢈", + "⢉", + "⢊", + "⢋", + "⢌", + "⢍", + "⢎", + "⢏", + "⣈", + "⣉", + "⣊", + "⣋", + "⣌", + "⣍", + "⣎", + "⣏", + "⢐", + "⢑", + "⢒", + "⢓", + "⢔", + "⢕", + "⢖", + "⢗", + "⣐", + "⣑", + "⣒", + "⣓", + "⣔", + "⣕", + "⣖", + "⣗", + "⢘", + "⢙", + "⢚", + "⢛", + "⢜", + "⢝", + "⢞", + "⢟", + "⣘", + "⣙", + "⣚", + "⣛", + "⣜", + "⣝", + "⣞", + "⣟", + "⢠", + "⢡", + "⢢", + "⢣", + "⢤", + "⢥", + "⢦", + "⢧", + "⣠", + "⣡", + "⣢", + "⣣", + "⣤", + "⣥", + "⣦", + "⣧", + "⢨", + "⢩", + "⢪", + "⢫", + "⢬", + "⢭", + "⢮", + "⢯", + "⣨", + "⣩", + "⣪", + "⣫", + "⣬", + "⣭", + "⣮", + "⣯", + "⢰", + "⢱", + "⢲", + "⢳", + "⢴", + "⢵", + "⢶", + "⢷", + "⣰", + "⣱", + "⣲", + "⣳", + "⣴", + "⣵", + "⣶", + "⣷", + "⢸", + "⢹", + "⢺", + "⢻", + "⢼", + "⢽", + "⢾", + "⢿", + "⣸", + "⣹", + "⣺", + "⣻", + "⣼", + "⣽", + "⣾", + "⣿" + ] + }, + "line": { + "interval": 130, + "frames": [ + "-", + "\\", + "|", + "/" + ] + }, + "line2": { + "interval": 100, + "frames": [ + "⠂", + "-", + "–", + "—", + "–", + "-" + ] + }, + "pipe": { + "interval": 100, + "frames": [ + "┤", + "┘", + "┴", + "└", + "├", + "┌", + "┬", + "┐" + ] + }, + "simpleDots": { + "interval": 400, + "frames": [ + ". ", + ".. ", + "...", + " " + ] + }, + "simpleDotsScrolling": { + "interval": 200, + "frames": [ + ". ", + ".. ", + "...", + " ..", + " .", + " " + ] + }, + "star": { + "interval": 70, + "frames": [ + "✶", + "✸", + "✹", + "✺", + "✹", + "✷" + ] + }, + "star2": { + "interval": 80, + "frames": [ + "+", + "x", + "*" + ] + }, + "flip": { + "interval": 70, + "frames": [ + "_", + "_", + "_", + "-", + "`", + "`", + "'", + "´", + "-", + "_", + "_", + "_" + ] + }, + "hamburger": { + "interval": 100, + "frames": [ + "☱", + "☲", + "☴" + ] + }, + "growVertical": { + "interval": 120, + "frames": [ + "▁", + "▃", + "▄", + "▅", + "▆", + "▇", + "▆", + "▅", + "▄", + "▃" + ] + }, + "growHorizontal": { + "interval": 120, + "frames": [ + "▏", + "▎", + "▍", + "▌", + "▋", + "▊", + "▉", + "▊", + "▋", + "▌", + "▍", + "▎" + ] + }, + "balloon": { + "interval": 140, + "frames": [ + " ", + ".", + "o", + "O", + "@", + "*", + " " + ] + }, + "balloon2": { + "interval": 120, + "frames": [ + ".", + "o", + "O", + "°", + "O", + "o", + "." + ] + }, + "noise": { + "interval": 100, + "frames": [ + "▓", + "▒", + "░" + ] + }, + "bounce": { + "interval": 120, + "frames": [ + "⠁", + "⠂", + "⠄", + "⠂" + ] + }, + "boxBounce": { + "interval": 120, + "frames": [ + "▖", + "▘", + "▝", + "▗" + ] + }, + "boxBounce2": { + "interval": 100, + "frames": [ + "▌", + "▀", + "▐", + "▄" + ] + }, + "triangle": { + "interval": 50, + "frames": [ + "◢", + "◣", + "◤", + "◥" + ] + }, + "arc": { + "interval": 100, + "frames": [ + "◜", + "◠", + "◝", + "◞", + "◡", + "◟" + ] + }, + "circle": { + "interval": 120, + "frames": [ + "◡", + "⊙", + "◠" + ] + }, + "squareCorners": { + "interval": 180, + "frames": [ + "◰", + "◳", + "◲", + "◱" + ] + }, + "circleQuarters": { + "interval": 120, + "frames": [ + "◴", + "◷", + "◶", + "◵" + ] + }, + "circleHalves": { + "interval": 50, + "frames": [ + "◐", + "◓", + "◑", + "◒" + ] + }, + "squish": { + "interval": 100, + "frames": [ + "╫", + "╪" + ] + }, + "toggle": { + "interval": 250, + "frames": [ + "⊶", + "⊷" + ] + }, + "toggle2": { + "interval": 80, + "frames": [ + "▫", + "▪" + ] + }, + "toggle3": { + "interval": 120, + "frames": [ + "□", + "■" + ] + }, + "toggle4": { + "interval": 100, + "frames": [ + "■", + "□", + "▪", + "▫" + ] + }, + "toggle5": { + "interval": 100, + "frames": [ + "▮", + "▯" + ] + }, + "toggle6": { + "interval": 300, + "frames": [ + "ဝ", + "၀" + ] + }, + "toggle7": { + "interval": 80, + "frames": [ + "⦾", + "⦿" + ] + }, + "toggle8": { + "interval": 100, + "frames": [ + "◍", + "◌" + ] + }, + "toggle9": { + "interval": 100, + "frames": [ + "◉", + "◎" + ] + }, + "toggle10": { + "interval": 100, + "frames": [ + "㊂", + "㊀", + "㊁" + ] + }, + "toggle11": { + "interval": 50, + "frames": [ + "⧇", + "⧆" + ] + }, + "toggle12": { + "interval": 120, + "frames": [ + "☗", + "☖" + ] + }, + "toggle13": { + "interval": 80, + "frames": [ + "=", + "*", + "-" + ] + }, + "arrow": { + "interval": 100, + "frames": [ + "←", + "↖", + "↑", + "↗", + "→", + "↘", + "↓", + "↙" + ] + }, + "arrow2": { + "interval": 80, + "frames": [ + "⬆️ ", + "↗️ ", + "➡️ ", + "↘️ ", + "⬇️ ", + "↙️ ", + "⬅️ ", + "↖️ " + ] + }, + "arrow3": { + "interval": 120, + "frames": [ + "▹▹▹▹▹", + "▸▹▹▹▹", + "▹▸▹▹▹", + "▹▹▸▹▹", + "▹▹▹▸▹", + "▹▹▹▹▸" + ] + }, + "bouncingBar": { + "interval": 80, + "frames": [ + "[ ]", + "[= ]", + "[== ]", + "[=== ]", + "[ ===]", + "[ ==]", + "[ =]", + "[ ]", + "[ =]", + "[ ==]", + "[ ===]", + "[====]", + "[=== ]", + "[== ]", + "[= ]" + ] + }, + "bouncingBall": { + "interval": 80, + "frames": [ + "( ● )", + "( ● )", + "( ● )", + "( ● )", + "( ●)", + "( ● )", + "( ● )", + "( ● )", + "( ● )", + "(● )" + ] + }, + "smiley": { + "interval": 200, + "frames": [ + "😄 ", + "😝 " + ] + }, + "monkey": { + "interval": 300, + "frames": [ + "🙈 ", + "🙈 ", + "🙉 ", + "🙊 " + ] + }, + "hearts": { + "interval": 100, + "frames": [ + "💛 ", + "💙 ", + "💜 ", + "💚 ", + "❤️ " + ] + }, + "clock": { + "interval": 100, + "frames": [ + "🕛 ", + "🕐 ", + "🕑 ", + "🕒 ", + "🕓 ", + "🕔 ", + "🕕 ", + "🕖 ", + "🕗 ", + "🕘 ", + "🕙 ", + "🕚 " + ] + }, + "earth": { + "interval": 180, + "frames": [ + "🌍 ", + "🌎 ", + "🌏 " + ] + }, + "material": { + "interval": 17, + "frames": [ + "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "███████▁▁▁▁▁▁▁▁▁▁▁▁▁", + "████████▁▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "██████████▁▁▁▁▁▁▁▁▁▁", + "███████████▁▁▁▁▁▁▁▁▁", + "█████████████▁▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁▁██████████████▁▁▁▁", + "▁▁▁██████████████▁▁▁", + "▁▁▁▁█████████████▁▁▁", + "▁▁▁▁██████████████▁▁", + "▁▁▁▁██████████████▁▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁██████████████▁", + "▁▁▁▁▁▁██████████████", + "▁▁▁▁▁▁██████████████", + "▁▁▁▁▁▁▁█████████████", + "▁▁▁▁▁▁▁█████████████", + "▁▁▁▁▁▁▁▁████████████", + "▁▁▁▁▁▁▁▁████████████", + "▁▁▁▁▁▁▁▁▁███████████", + "▁▁▁▁▁▁▁▁▁███████████", + "▁▁▁▁▁▁▁▁▁▁██████████", + "▁▁▁▁▁▁▁▁▁▁██████████", + "▁▁▁▁▁▁▁▁▁▁▁▁████████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "██████▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "████████▁▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "█████████▁▁▁▁▁▁▁▁▁▁▁", + "███████████▁▁▁▁▁▁▁▁▁", + "████████████▁▁▁▁▁▁▁▁", + "████████████▁▁▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "██████████████▁▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁██████████████▁▁▁▁▁", + "▁▁▁█████████████▁▁▁▁", + "▁▁▁▁▁████████████▁▁▁", + "▁▁▁▁▁████████████▁▁▁", + "▁▁▁▁▁▁███████████▁▁▁", + "▁▁▁▁▁▁▁▁█████████▁▁▁", + "▁▁▁▁▁▁▁▁█████████▁▁▁", + "▁▁▁▁▁▁▁▁▁█████████▁▁", + "▁▁▁▁▁▁▁▁▁█████████▁▁", + "▁▁▁▁▁▁▁▁▁▁█████████▁", + "▁▁▁▁▁▁▁▁▁▁▁████████▁", + "▁▁▁▁▁▁▁▁▁▁▁████████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", + "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁" + ] + }, + "moon": { + "interval": 80, + "frames": [ + "🌑 ", + "🌒 ", + "🌓 ", + "🌔 ", + "🌕 ", + "🌖 ", + "🌗 ", + "🌘 " + ] + }, + "runner": { + "interval": 140, + "frames": [ + "🚶 ", + "🏃 " + ] + }, + "pong": { + "interval": 80, + "frames": [ + "▐⠂ ▌", + "▐⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂▌", + "▐ ⠠▌", + "▐ ⡀▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐ ⠠ ▌", + "▐ ⠂ ▌", + "▐ ⠈ ▌", + "▐ ⠂ ▌", + "▐ ⠠ ▌", + "▐ ⡀ ▌", + "▐⠠ ▌" + ] + }, + "shark": { + "interval": 120, + "frames": [ + "▐|\\____________▌", + "▐_|\\___________▌", + "▐__|\\__________▌", + "▐___|\\_________▌", + "▐____|\\________▌", + "▐_____|\\_______▌", + "▐______|\\______▌", + "▐_______|\\_____▌", + "▐________|\\____▌", + "▐_________|\\___▌", + "▐__________|\\__▌", + "▐___________|\\_▌", + "▐____________|\\▌", + "▐____________/|▌", + "▐___________/|_▌", + "▐__________/|__▌", + "▐_________/|___▌", + "▐________/|____▌", + "▐_______/|_____▌", + "▐______/|______▌", + "▐_____/|_______▌", + "▐____/|________▌", + "▐___/|_________▌", + "▐__/|__________▌", + "▐_/|___________▌", + "▐/|____________▌" + ] + }, + "dqpb": { + "interval": 100, + "frames": [ + "d", + "q", + "p", + "b" + ] + }, + "weather": { + "interval": 100, + "frames": [ + "☀️ ", + "☀️ ", + "☀️ ", + "🌤 ", + "⛅️ ", + "🌥 ", + "☁️ ", + "🌧 ", + "🌨 ", + "🌧 ", + "🌨 ", + "🌧 ", + "🌨 ", + "⛈ ", + "🌨 ", + "🌧 ", + "🌨 ", + "☁️ ", + "🌥 ", + "⛅️ ", + "🌤 ", + "☀️ ", + "☀️ " + ] + }, + "christmas": { + "interval": 400, + "frames": [ + "🌲", + "🎄" + ] + }, + "grenade": { + "interval": 80, + "frames": [ + "، ", + "′ ", + " ´ ", + " ‾ ", + " ⸌", + " ⸊", + " |", + " ⁎", + " ⁕", + " ෴ ", + " ⁓", + " ", + " ", + " " + ] + }, + "point": { + "interval": 125, + "frames": [ + "∙∙∙", + "●∙∙", + "∙●∙", + "∙∙●", + "∙∙∙" + ] + }, + "layer": { + "interval": 150, + "frames": [ + "-", + "=", + "≡" + ] + }, + "betaWave": { + "interval": 80, + "frames": [ + "ρββββββ", + "βρβββββ", + "ββρββββ", + "βββρβββ", + "ββββρββ", + "βββββρβ", + "ββββββρ" + ] + }, + "fingerDance": { + "interval": 160, + "frames": [ + "🤘 ", + "🤟 ", + "🖖 ", + "✋ ", + "🤚 ", + "👆 " + ] + }, + "fistBump": { + "interval": 80, + "frames": [ + "🤜\u3000\u3000\u3000\u3000🤛 ", + "🤜\u3000\u3000\u3000\u3000🤛 ", + "🤜\u3000\u3000\u3000\u3000🤛 ", + "\u3000🤜\u3000\u3000🤛\u3000 ", + "\u3000\u3000🤜🤛\u3000\u3000 ", + "\u3000🤜✨🤛\u3000\u3000 ", + "🤜\u3000✨\u3000🤛\u3000 " + ] + }, + "soccerHeader": { + "interval": 80, + "frames": [ + " 🧑⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 ", + "🧑 ⚽️ 🧑 " + ] + }, + "mindblown": { + "interval": 160, + "frames": [ + "😐 ", + "😐 ", + "😮 ", + "😮 ", + "😦 ", + "😦 ", + "😧 ", + "😧 ", + "🤯 ", + "💥 ", + "✨ ", + "\u3000 ", + "\u3000 ", + "\u3000 " + ] + }, + "speaker": { + "interval": 160, + "frames": [ + "🔈 ", + "🔉 ", + "🔊 ", + "🔉 " + ] + }, + "orangePulse": { + "interval": 100, + "frames": [ + "🔸 ", + "🔶 ", + "🟠 ", + "🟠 ", + "🔶 " + ] + }, + "bluePulse": { + "interval": 100, + "frames": [ + "🔹 ", + "🔷 ", + "🔵 ", + "🔵 ", + "🔷 " + ] + }, + "orangeBluePulse": { + "interval": 100, + "frames": [ + "🔸 ", + "🔶 ", + "🟠 ", + "🟠 ", + "🔶 ", + "🔹 ", + "🔷 ", + "🔵 ", + "🔵 ", + "🔷 " + ] + }, + "timeTravel": { + "interval": 100, + "frames": [ + "🕛 ", + "🕚 ", + "🕙 ", + "🕘 ", + "🕗 ", + "🕖 ", + "🕕 ", + "🕔 ", + "🕓 ", + "🕒 ", + "🕑 ", + "🕐 " + ] + }, + "aesthetic": { + "interval": 80, + "frames": [ + "▰▱▱▱▱▱▱", + "▰▰▱▱▱▱▱", + "▰▰▰▱▱▱▱", + "▰▰▰▰▱▱▱", + "▰▰▰▰▰▱▱", + "▰▰▰▰▰▰▱", + "▰▰▰▰▰▰▰", + "▰▱▱▱▱▱▱" + ] + } +} diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/whirly-static-spinners.json b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/whirly-static-spinners.json new file mode 100644 index 0000000000000..3c99177d155fc --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/whirly-static-spinners.json @@ -0,0 +1,274 @@ +{ + "roman_numerals": { + "interval": 90, + "mode": "swing", + "frames": [ + "Ⅰ", + "Ⅱ", + "Ⅲ", + "Ⅳ", + "Ⅴ", + "Ⅵ", + "Ⅶ", + "Ⅷ", + "Ⅸ", + "Ⅹ" + ] + }, + "double_mark": { + "interval": 120, + "mode": "random", + "frames": [ + "⁇", + "⁈", + "⁉", + "‼" + ] + }, + "heart_exclamation": { + "interval": 45, + "frames": [ + "❢", + "❣" + ] + }, + "pencil": { + "interval": 200, + "frames": [ + "✏", + "✎" + ] + }, + "bars": { + "interval": 80, + "mode": "swing", + "frames": [ + "𝍠", + "𝍡", + "𝍢", + "𝍣", + "𝍤" + ] + }, + "dice": { + "interval": 100, + "mode": "random", + "frames": [ + "⚀", + "⚁", + "⚂", + "⚃", + "⚄", + "⚅" + ] + }, + "hanoi": { + "interval": 150, + "mode": "swing", + "frames": [ + "𝍥", + "𝍦", + "𝍧", + "𝍨" + ] + }, + "vertical_bars": { + "interval": 80, + "mode": "swing", + "frames": [ + "𝍩", + "𝍪", + "𝍫", + "𝍬", + "𝍭" + ] + }, + "whirly": { + "interval": 200, + "mode": "random", + "frames": [ + "😀", + "😁", + "😂", + "😃", + "😄", + "😅", + "😆", + "😇", + "😈", + "😉", + "😊", + "😋", + "😌", + "😍", + "😎", + "😏", + "😐", + "😑", + "😒", + "😓", + "😔", + "😕", + "😖", + "😗", + "😘", + "😙", + "😚", + "😛", + "😜", + "😝", + "😞", + "😟", + "😠", + "😡", + "😢", + "😣", + "😤", + "😥", + "😦", + "😧", + "😨", + "😩", + "😪", + "😫", + "😬", + "😭", + "😮", + "😯", + "😰", + "😱", + "😲", + "😳", + "😴", + "😵", + "😶", + "🙁", + "🙂", + "🙃", + "🙄", + "😷", + "🤐", + "🤑", + "🤒", + "🤓", + "🤔", + "🤕", + "🤖", + "🤗" + ] + }, + "cat": { + "interval": 200, + "mode": "random", + "frames": [ + "😸", + "😹", + "😺", + "😻", + "😼", + "😽", + "😾", + "😿", + "🙀" + ] + }, + "card": { + "interval": 90, + "stop": "🂠", + "frames": [ + "🃁", "🃂", "🃃", "🃄", "🃅", "🃆", "🃇", "🃈", "🃉", "🃊", "🃋", "🃌", "🃍", "🃎", + "🂱", "🂲", "🂳", "🂴", "🂵", "🂶", "🂷", "🂸", "🂹", "🂺", "🂻", "🂼", "🂽", "🂾", + "🂡", "🂢", "🂣", "🂤", "🂥", "🂦", "🂧", "🂨", "🂩", "🂪", "🂫", "🂬", "🂭", "🂮", + "🃑", "🃒", "🃓", "🃔", "🃕", "🃖", "🃗", "🃘", "🃙", "🃚", "🃛", "🃜", "🃝", "🃞" + ] + }, + "cloud": { + "interval": 140, + "frames": [ + "🌥", + "🌦", + "🌧", + "🌨", + "🌩", + "🌪" + ] + }, + "photo": { + "interval": 200, + "frames": [ + "📷", + "📸" + ] + }, + "banknote": { + "interval": 100, + "frames": [ + "💴", + "💵", + "💶", + "💷" + ] + }, + "white_square": { + "interval": 100, + "mode": "swing", + "frames": [ + "🞓", + "🞒", + "🞑", + "🞐", + "🞏", + "🞎", + "🞔" + ] + }, + "xberg": { + "interval": 150, + "mode": "random", + "frames": [ + "⨯", + "⛰", + "⛰", + "⛰", + "⛰", + "⛰", + "⛰" + ] + }, + "circled_letter": { + "interval": 120, + "mode": "random", + "frames": [ + "Ⓐ", "Ⓑ", "Ⓒ", "Ⓓ", "Ⓔ", "Ⓕ", "Ⓖ", "Ⓗ", "Ⓘ", + "Ⓙ", "Ⓚ", "Ⓛ", "Ⓜ", "Ⓝ", "Ⓞ", "Ⓟ", "Ⓠ", "Ⓡ", + "Ⓢ", "Ⓣ", "Ⓤ", "Ⓥ", "Ⓦ", "Ⓧ", "Ⓨ", "Ⓩ" + ] + }, + "circled_number": { + "interval": 120, + "mode": "random", + "frames": [ + "①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "⑨" + ] + }, + "letter_with_parens": { + "interval": 150, + "mode": "random", + "frames": [ + "🄐", "🄑", "🄒", "🄓", "🄔", "🄕", "🄖", "🄗", "🄘", + "🄙", "🄚", "🄛", "🄜", "🄝", "🄞", "🄟", "🄠", "🄡", + "🄢", "🄣", "🄤", "🄥", "🄦", "🄧", "🄨", "🄩" + ] + }, + "starlike": { + "interval": 120, + "mode": "random", + "frames": [ + "✩", "✪", "✫", "✬", "✭", "✮", "✯", "✰", + "✱", "✲", "✳", "✴", "✵", "✶", "✷", "✸", + "✹", "✺", "✻", "✼", "✽", "✾", "✿", "❀", + "❁", "❂", "❃", "❄", "❅", "❆", "❇", "❈", + "❉", "❊" + ] + } +} diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly.rb new file mode 100644 index 0000000000000..5106fc7c06e5e --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly.rb @@ -0,0 +1,263 @@ +require_relative "whirly/version" +require_relative "whirly/spinners" + +require "unicode/display_width" + +begin + require "paint" +rescue LoadError +end + +module Whirly + @configured = false + + CLI_COMMANDS = { + hide_cursor: "\x1b[?25l", + show_cursor: "\x1b[?25h", + }.freeze + + DEFAULT_OPTIONS = { + ambiguous_character_width: 1, + ansi_escape_mode: "restore", + append_newline: true, + color: !!defined?(Paint), + color_change_rate: 30, + hide_cursor: true, + non_tty: false, + position: "normal", + remove_after_stop: false, + spinner: "whirly", + spinner_packs: [:whirly, :cli], + status: nil, + stream: $stdout, + }.freeze + + SOFT_DEFAULT_OPTIONS = { + interval: 100, + mode: "linear", + stop: nil, + }.freeze + + class << self + attr_accessor :status + attr_reader :options + + def enabled? + !!(defined?(@enabled) && @enabled) + end + + def configured? + !!(@configured) + end + end + + # set spinner directly or lookup + def self.configure_spinner(spinner_option) + case spinner_option + when Hash + spinner = spinner_option.dup + when Enumerable + spinner = { "frames" => spinner_option.dup } + when Proc + spinner = { "proc" => spinner_option.dup } + else + spinner = nil + catch(:found){ + @options[:spinner_packs].each{ |spinner_pack| + spinners = Whirly::Spinners.const_get(spinner_pack.to_s.upcase) + if spinners[spinner_option] + spinner = spinners[spinner_option].dup + throw(:found) + end + } + } + end + + # validate spinner + if !spinner || (!spinner["frames"] && !spinner["proc"]) + raise(ArgumentError, "Whirly: Invalid spinner given") + end + + spinner + end + + # frames can be generated from enumerables or procs + def self.configure_frames(spinner) + if spinner["frames"] + case spinner["mode"] + when "swing" + frames = (spinner["frames"].to_a + spinner["frames"].to_a[1..-2].reverse).cycle + when "random" + frame_pool = spinner["frames"].to_a + frames = ->(){ frame_pool.sample } + when "reverse" + frames = spinner["frames"].to_a.reverse.cycle + else + frames = spinner["frames"].cycle + end + elsif spinner["proc"] + frames = spinner["proc"].dup + else + raise(ArgumentError, "Whirly: Invalid spinner given") + end + + if frames.is_a? Proc + class << frames + alias next call + end + end + + frames + end + + # save options and preprocess, set defaults if value is still unknown + def self.configure(**options) + if !defined?(@configured) || !@configured || !defined?(@options) || !@options + @options = DEFAULT_OPTIONS.dup + @configured = true + end + + @options.merge!(options) + + spinner = configure_spinner(@options[:spinner]) + spinner_overwrites = {} + spinner_overwrites["mode"] = @options[:mode] if @options.key?(:mode) + @frames = configure_frames(spinner.merge(spinner_overwrites)) + + @interval = (@options[:interval] || spinner["interval"] || SOFT_DEFAULT_OPTIONS[:interval]) * 0.001 + @stop = @options[:stop] || spinner["stop"] + @status = @options[:status] + end + + def self.start(**options) + # optionally overwrite configuration on start + configure(**options) + + # only enable once + return false if defined?(@enabled) && @enabled + + # set status to enabled + @enabled = true + + # only do something if we are on a real terminal (or forced) + return false unless @options[:stream].tty? || @options[:non_tty] + + # ensure cursor is visible after exit the program (only register for the very first time) + if (!defined?(@at_exit_handler_registered) || !@at_exit_handler_registered) && @options[:hide_cursor] + @at_exit_handler_registered = true + stream = @options[:stream] + at_exit{ stream.print CLI_COMMANDS[:show_cursor] } + end + + # init color + initialize_color if @options[:color] + + # hide cursor + @options[:stream].print CLI_COMMANDS[:hide_cursor] if @options[:hide_cursor] + + # start spinner loop + @thread = Thread.new do + @current_frame = nil + while true # it's just a spinner, no exact timing here + next_color if @color + render + sleep(@interval) + end + end + + # idiomatic block syntax support + if block_given? + begin + yield + ensure + Whirly.stop + end + end + + true + end + + def self.stop(stop_frame = nil) + return false unless @enabled + @enabled = false + return false unless @options[:stream].tty? || @options[:non_tty] + + @thread.terminate if @thread + render(stop_frame || @stop) if stop_frame || @stop + unrender if @options[:remove_after_stop] + @options[:stream].puts if @options[:append_newline] + @options[:stream].print CLI_COMMANDS[:show_cursor] if @options[:hide_cursor] + + true + end + + def self.reset + at_exit_handler_registered = defined?(@at_exit_handler_registered) && @at_exit_handler_registered + instance_variables.each{ |iv| remove_instance_variable(iv) } + @at_exit_handler_registered = at_exit_handler_registered + @configured = false + end + + # - - - + + def self.unrender + return unless @current_frame + case @options[:ansi_escape_mode] + when "restore" + @options[:stream].print(render_prefix + ( + ' ' * (Unicode::DisplayWidth.of(@current_frame, @options[:ambiguous_character_width]) + 1) + ) + render_suffix) + when "line" + @options[:stream].print "\e[1K" + end + end + + def self.render(next_frame = nil) + unrender + + @current_frame = next_frame || @frames.next + @current_frame = Paint[@current_frame, @color] if @options[:color] + @current_frame += " #{@status}" if @status + + @options[:stream].print(render_prefix + @current_frame.to_s + render_suffix) + end + + def self.render_prefix + res = "" + res << "\n" if @options[:position] == "below" + res << "\e7" if @options[:ansi_escape_mode] == "restore" + res << "\e[G" if @options[:ansi_escape_mode] == "line" + res + end + + def self.render_suffix + res = "" + res << "\e8" if @options[:ansi_escape_mode] == "restore" + res << "\e[1A" if @options[:position] == "below" + res + end + + def self.initialize_color + if !defined?(Paint) + warn "Whirly warning: Using colors requires the paint gem" + else + @color = "%.6x" % rand(16777216) + @color_directions = (0..2).map{ |e| rand(3) - 1 } + end + end + + def self.next_color + @color = @color.scan(/../).map.with_index{ |c, i| + color_change = rand(@options[:color_change_rate]) * @color_directions[i] + nc = c.to_i(16) + color_change + if nc <= 0 + nc = 0 + @color_directions[i] = rand(3) - 1 + elsif nc >= 255 + nc = 255 + @color_directions[i] = rand(3) - 1 + end + "%.2x" % nc + }.join + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners.rb new file mode 100644 index 0000000000000..c72b037ae8655 --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners.rb @@ -0,0 +1,7 @@ +module Whirly + module Spinners + end +end + +require_relative "spinners/whirly" +require_relative "spinners/cli" diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/cli.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/cli.rb new file mode 100644 index 0000000000000..4fd2774730f6b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/cli.rb @@ -0,0 +1,7 @@ +require "json" + +module Whirly + module Spinners + CLI = JSON.load(File.read(File.dirname(__FILE__) + "/../../../data/cli-spinners.json")).freeze + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/whirly.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/whirly.rb new file mode 100644 index 0000000000000..f40853b0cd17b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/whirly.rb @@ -0,0 +1,15 @@ +require "json" + +module Whirly + module Spinners + WHIRLY = { + "random_dots" => { "proc" => ->(){ [ 0x2800 + rand(256)].pack("U") }, "interval" => 100 }, + "mahjong" => { "proc" => ->(){ [0x1F000 + rand(44)].pack("U") }, "interval" => 200 }, + "domino" => { "proc" => ->(){ [0x1F030 + rand(50)].pack("U") }, "interval" => 200 }, + "vertical_domino" => { "proc" => ->(){ [0x1F062 + rand(50)].pack("U") }, "interval" => 200 } + } + WHIRLY.merge! JSON.load(File.read(File.dirname(__FILE__) + "/../../../data/whirly-static-spinners.json")) + + WHIRLY.freeze + end +end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/version.rb new file mode 100644 index 0000000000000..4e33cef7c707b --- /dev/null +++ b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module Whirly + VERSION = "0.3.0" +end From b297be77a14f537db4b1d7cf63807f2b95dad5b5 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 14 Jul 2024 11:42:22 -0400 Subject: [PATCH 02/28] Implement concurrent downloads. --- Library/Homebrew/Gemfile | 2 +- Library/Homebrew/cask/download.rb | 12 +- Library/Homebrew/cmd/fetch.rb | 115 +++++++----------- Library/Homebrew/download_queue.rb | 30 +++++ Library/Homebrew/downloadable.rb | 21 +++- Library/Homebrew/formula.rb | 13 +- Library/Homebrew/patch.rb | 2 +- Library/Homebrew/resource.rb | 27 +++- Library/Homebrew/retryable_download.rb | 70 +++++++++++ Library/Homebrew/software_spec.rb | 67 ++++++---- .../sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi | 3 + Library/Homebrew/test/patch_spec.rb | 2 +- 12 files changed, 260 insertions(+), 104 deletions(-) create mode 100644 Library/Homebrew/download_queue.rb create mode 100644 Library/Homebrew/retryable_download.rb diff --git a/Library/Homebrew/Gemfile b/Library/Homebrew/Gemfile index 4eca964e9ff6a..17f0e703f4489 100644 --- a/Library/Homebrew/Gemfile +++ b/Library/Homebrew/Gemfile @@ -84,4 +84,4 @@ gem "plist" gem "ruby-macho" gem "sorbet-runtime" gem "warning" -gem 'whirly' +gem "whirly" diff --git a/Library/Homebrew/cask/download.rb b/Library/Homebrew/cask/download.rb index 075396a47e75c..836825abf538c 100644 --- a/Library/Homebrew/cask/download.rb +++ b/Library/Homebrew/cask/download.rb @@ -8,7 +8,7 @@ module Cask # A download corresponding to a {Cask}. - class Download < ::Downloadable + class Download < Downloadable include Context attr_reader :cask @@ -20,6 +20,11 @@ def initialize(cask, quarantine: nil) @quarantine = quarantine end + sig { override.returns(String) } + def name + cask.token + end + sig { override.returns(T.nilable(::URL)) } def url return if cask.url.nil? @@ -88,6 +93,11 @@ def download_name cask.token end + sig { override.returns(String) } + def download_type + "cask" + end + private def quarantine(path) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 96eca371d3cbd..15eecf70b7ecd 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -5,6 +5,8 @@ require "formula" require "fetch" require "cask/download" +require "retryable_download" +require "whirly" module Homebrew module Cmd @@ -25,6 +27,7 @@ class FetchCmd < AbstractCommand "(Pass `all` to download for all architectures.)" flag "--bottle-tag=", description: "Download a bottle for given tag." + flag "--concurrency=", description: "Number of concurrent downloads.", hidden: true switch "--HEAD", description: "Fetch HEAD version instead of stable version." switch "-f", "--force", @@ -67,6 +70,17 @@ class FetchCmd < AbstractCommand named_args [:formula, :cask], min: 1 end + def concurrency + @concurrency ||= args.concurrency&.to_i || 1 + end + + def download_queue + @download_queue ||= begin + require "download_queue" + DownloadQueue.new(concurrency) + end + end + sig { override.void } def run Formulary.enable_factory_cache! @@ -125,13 +139,10 @@ def run next end - begin - bottle.fetch_tab - rescue DownloadError - retry if retry_fetch?(bottle) - raise + if (manifest_resource = bottle.github_packages_manifest_resource) + fetch_downloadable(manifest_resource) end - fetch_formula(bottle) + fetch_downloadable(bottle) rescue Interrupt raise rescue => e @@ -147,14 +158,14 @@ def run next if fetched_bottle - fetch_formula(formula) + fetch_downloadable(formula.resource) formula.resources.each do |r| - fetch_resource(r) - r.patches.each { |p| fetch_patch(p) if p.external? } + fetch_downloadable(r) + r.patches.each { |patch| fetch_downloadable(patch.resource) if patch.external? } end - formula.patchlist.each { |p| fetch_patch(p) if p.external? } + formula.patchlist.each { |patch| fetch_downloadable(patch.resource) if patch.external? } end end else @@ -176,81 +187,43 @@ def run quarantine = true if quarantine.nil? download = Cask::Download.new(cask, quarantine:) - fetch_cask(download) + fetch_downloadable(download) end end end end - end - private + downloads.each do |downloadable, promise| + message = "#{downloadable.download_type.capitalize} #{downloadable.name}" + if concurrency > 1 + Whirly.start spinner: "arc", status: message + else + puts message + end - def fetch_resource(resource) - puts "Resource: #{resource.name}" - fetch_fetchable resource - rescue ChecksumMismatchError => e - retry if retry_fetch?(resource) - opoo "Resource #{resource.name} reports different sha256: #{e.expected}" - end + promise.wait! - def fetch_formula(formula) - fetch_fetchable(formula) - rescue ChecksumMismatchError => e - retry if retry_fetch?(formula) - opoo "Formula reports different sha256: #{e.expected}" - end + Whirly.configure stop: "✔︎" + Whirly.stop if args.concurrency + rescue ChecksumMismatchError => e + Whirly.configure stop: "✘" + Whirly.stop if args.concurrency - def fetch_cask(cask_download) - fetch_fetchable(cask_download) - rescue ChecksumMismatchError => e - retry if retry_fetch?(cask_download) - opoo "Cask reports different sha256: #{e.expected}" - end + opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" + Homebrew.failed = true if downloadable.is_a?(Resource::Patch) + end - def fetch_patch(patch) - fetch_fetchable(patch) - rescue ChecksumMismatchError => e - opoo "Patch reports different sha256: #{e.expected}" - Homebrew.failed = true + download_queue.shutdown end - def retry_fetch?(formula) - @fetch_tries ||= Hash.new { |h, k| h[k] = 1 } - if args.retry? && (@fetch_tries[formula] < FETCH_MAX_TRIES) - wait = 2 ** @fetch_tries[formula] - remaining = FETCH_MAX_TRIES - @fetch_tries[formula] - what = Utils.pluralize("tr", remaining, plural: "ies", singular: "y") - - ohai "Retrying download in #{wait}s... (#{remaining} #{what} left)" - sleep wait + private - formula.clear_cache - @fetch_tries[formula] += 1 - true - else - Homebrew.failed = true - false - end + def downloads + @downloads ||= {} end - def fetch_fetchable(formula) - formula.clear_cache if args.force? - - already_fetched = formula.cached_download.exist? - - begin - download = formula.fetch(verify_download_integrity: false) - rescue DownloadError - retry if retry_fetch?(formula) - raise - end - - return unless download.file? - - puts "Downloaded to: #{download}" unless already_fetched - puts "SHA256: #{download.sha256}" - - formula.verify_download_integrity(download) + def fetch_downloadable(downloadable) + downloads[downloadable] ||= download_queue.enqueue(RetryableDownload.new(downloadable)) end end end diff --git a/Library/Homebrew/download_queue.rb b/Library/Homebrew/download_queue.rb new file mode 100644 index 0000000000000..18c7e29489d25 --- /dev/null +++ b/Library/Homebrew/download_queue.rb @@ -0,0 +1,30 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +require "downloadable" +require "concurrent" + +module Homebrew + class DownloadQueue + sig { returns(Concurrent::FixedThreadPool) } + attr_reader :pool + private :pool + + sig { params(size: Integer).void } + def initialize(size = 1) + @pool = Concurrent::FixedThreadPool.new(size) + end + + sig { params(downloadable: Downloadable).returns(Concurrent::Promise) } + def enqueue(downloadable) + Concurrent::Promise.execute(executor: pool) do + downloadable.fetch(quiet: pool.max_length > 1) + end + end + + sig { void } + def shutdown + pool.shutdown + end + end +end diff --git a/Library/Homebrew/downloadable.rb b/Library/Homebrew/downloadable.rb index 9a82d99f4ee5d..b030c60678f76 100644 --- a/Library/Homebrew/downloadable.rb +++ b/Library/Homebrew/downloadable.rb @@ -40,6 +40,16 @@ def freeze super end + sig { returns(String) } + def name + "" + end + + sig { returns(String) } + def download_type + T.must(T.must(self.class.name).split("::").last).gsub(/([[:lower:]])([[:upper:]])/, '\1 \2').downcase + end + sig { returns(T::Boolean) } def downloaded? cached_download.exist? @@ -79,11 +89,18 @@ def downloader end end - sig { params(verify_download_integrity: T::Boolean, timeout: T.nilable(T.any(Integer, Float))).returns(Pathname) } - def fetch(verify_download_integrity: true, timeout: nil) + sig { + params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T::Boolean, + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) cache.mkpath begin + downloader.quiet! if quiet downloader.fetch(timeout:) rescue ErrorDuringExecution, CurlDownloadStrategyError => e raise DownloadError.new(self, e) diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 75e1a2a06612d..62c88710f13c1 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -567,7 +567,7 @@ def synced_with_other_formulae? params(name: String, klass: T.class_of(Resource), block: T.nilable(T.proc.bind(Resource).void)) .returns(T.nilable(Resource)) } - def resource(name, klass = Resource, &block) = active_spec.resource(name, klass, &block) + def resource(name = T.unsafe(nil), klass = T.unsafe(nil), &block) = active_spec.resource(*name, *klass, &block) # Old names for the formula. # @@ -2765,8 +2765,15 @@ def on_system_blocks_exist? self.class.on_system_blocks_exist? || @on_system_blocks_exist end - def fetch(verify_download_integrity: true) - active_spec.fetch(verify_download_integrity:) + sig { + params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T::Boolean, + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) + active_spec.fetch(verify_download_integrity:, timeout:, quiet:) end def verify_download_integrity(filename) diff --git a/Library/Homebrew/patch.rb b/Library/Homebrew/patch.rb index 6aacc0254b0cf..39e67b1d24031 100644 --- a/Library/Homebrew/patch.rb +++ b/Library/Homebrew/patch.rb @@ -106,7 +106,7 @@ class ExternalPatch def initialize(strip, &block) @strip = strip - @resource = Resource::PatchResource.new(&block) + @resource = Resource::Patch.new(&block) end sig { returns(T::Boolean) } diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index 61ce2eb408af1..59607548de037 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -140,7 +140,15 @@ def files(*files) Partial.new(self, files) end - def fetch(verify_download_integrity: true) + sig { + override + .params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T::Boolean, + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) fetch_patches super @@ -211,7 +219,7 @@ def mirror(val) end def patch(strip = :p1, src = nil, &block) - p = Patch.create(strip, src, &block) + p = ::Patch.create(strip, src, &block) patches << p end @@ -260,6 +268,19 @@ def determine_url_mirrors [*extra_urls, *super].uniq end + # A resource for a formula. + class Formula < Resource + sig { override.returns(String) } + def name + T.must(owner).name + end + + sig { override.returns(String) } + def download_name + name + end + end + # A resource containing a Go package. class Go < Resource def stage(target, &block) @@ -320,7 +341,7 @@ def tab end # A resource containing a patch. - class PatchResource < Resource + class Patch < Resource attr_reader :patch_files def initialize(&block) diff --git a/Library/Homebrew/retryable_download.rb b/Library/Homebrew/retryable_download.rb new file mode 100644 index 0000000000000..bd9d9e595c50b --- /dev/null +++ b/Library/Homebrew/retryable_download.rb @@ -0,0 +1,70 @@ +# typed: true # rubocop:todo Sorbet/StrictSigil +# frozen_string_literal: true + +module Homebrew + class RetryableDownload < Downloadable + sig { returns(Downloadable) } + attr_reader :downloadable + private :downloadable + + sig { params(downloadable: Downloadable, tries: Integer).void } + def initialize(downloadable, tries: 3) + super() + + @downloadable = downloadable + @try = 0 + @tries = tries + end + + sig { override.returns(String) } + def name = downloadable.name + + sig { override.returns(String) } + def download_type = downloadable.download_type + + sig { override.returns(T::Boolean) } + def downloaded? = downloadable.downloaded? + + sig { override.returns(Pathname) } + def cached_download = downloadable.cached_download + + sig { + override.params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T::Boolean, + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) + @try += 1 + + already_downloaded = downloadable.downloaded? + + download = downloadable.fetch(verify_download_integrity: false, timeout:, quiet:) + + return download unless download.file? + + unless quiet + puts "Downloaded to: #{download}" unless already_downloaded + puts "SHA256: #{download.sha256}" + end + + downloadable.verify_download_integrity(download) if verify_download_integrity + + download + rescue DownloadError, ChecksumMismatchError + tries_remaining = @tries - @try + raise if tries_remaining.zero? + + wait = 2 ** @try + unless quiet + what = Utils.pluralize("tr", tries_remaining, plural: "ies", singular: "y") + ohai "Retrying download in #{wait}s... (#{tries_remaining} #{what} left)" + end + sleep wait + + downloadable.clear_cache + retry + end + end +end diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index ebf7821dad9bb..305319e88c0bc 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -15,7 +15,7 @@ require "macos_version" require "extend/on_system" -class SoftwareSpec +class SoftwareSpec < Downloadable extend Forwardable include OnSystem::MacOSAndLinux @@ -34,8 +34,10 @@ class SoftwareSpec def_delegators :@resource, :sha256 def initialize(flags: []) + super() + # Ensure this is synced with `initialize_dup` and `freeze` (excluding simple objects like integers and booleans) - @resource = Resource.new + @resource = Resource::Formula.new @resources = {} @dependency_collector = DependencyCollector.new @bottle_specification = BottleSpecification.new @@ -78,6 +80,11 @@ def freeze super end + sig { override.returns(String) } + def download_type + "formula" + end + def owner=(owner) @name = owner.name @full_name = owner.full_name @@ -126,8 +133,9 @@ def resource_defined?(name) params(name: String, klass: T.class_of(Resource), block: T.nilable(T.proc.bind(Resource).void)) .returns(T.nilable(Resource)) } - def resource(name, klass = Resource, &block) + def resource(name = T.unsafe(nil), klass = Resource, &block) if block + raise ArgumentError, "Resource must have a name." if name.nil? raise DuplicateResourceError, name if resource_defined?(name) res = klass.new(name, &block) @@ -137,6 +145,8 @@ def resource(name, klass = Resource, &block) dependency_collector.add(res) res else + return @resource if name.nil? + resources.fetch(name) { raise ResourceMissingError.new(owner, name) } end end @@ -284,7 +294,7 @@ def verify_download_integrity(_filename) end end -class Bottle +class Bottle < Downloadable class Filename attr_reader :name, :version, :tag, :rebuild @@ -341,6 +351,8 @@ def extname def_delegators :resource, :cached_download def initialize(formula, spec, tag = nil) + super() + @name = formula.name @resource = Resource.new @resource.owner = formula @@ -360,8 +372,15 @@ def initialize(formula, spec, tag = nil) root_url(spec.root_url, spec.root_url_specs) end - def fetch(verify_download_integrity: true) - @resource.fetch(verify_download_integrity:) + sig { + override.params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T.nilable(T::Boolean), + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) + resource.fetch(verify_download_integrity:, timeout:, quiet:) rescue DownloadError raise unless fallback_on_error @@ -369,6 +388,7 @@ def fetch(verify_download_integrity: true) retry end + sig { override.void } def clear_cache @resource.clear_cache github_packages_manifest_resource&.clear_cache @@ -388,26 +408,30 @@ def stage resource.downloader.stage end - def fetch_tab - return if github_packages_manifest_resource.blank? + def fetch_tab(timeout: nil, quiet: false) + return unless (resource = github_packages_manifest_resource) - github_packages_manifest_resource.fetch - rescue DownloadError - raise unless fallback_on_error + begin + resource.fetch(timeout:, quiet:) + rescue DownloadError + raise unless fallback_on_error - retry - rescue ArgumentError - raise if @fetch_tab_retried + retry + rescue ArgumentError + raise if @fetch_tab_retried - @fetch_tab_retried = true - github_packages_manifest_resource.clear_cache - retry + @fetch_tab_retried = true + resource.clear_cache + retry + end end def tab_attributes - return {} unless github_packages_manifest_resource&.downloaded? + if (resource = github_packages_manifest_resource) && resource.downloaded? + return resource.tab + end - github_packages_manifest_resource.tab + {} end sig { returns(Filename) } @@ -415,8 +439,7 @@ def filename Filename.create(resource.owner, @tag, @spec.rebuild) end - private - + sig { returns(T.nilable(Resource::BottleManifest)) } def github_packages_manifest_resource return if @resource.download_strategy != CurlGitHubPackagesDownloadStrategy @@ -439,6 +462,8 @@ def github_packages_manifest_resource end end + private + def select_download_strategy(specs) specs[:using] ||= DownloadStrategyDetector.detect(@root_url) specs[:bottle] = true diff --git a/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi b/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi index 9275df2ee4a4a..b90b857ce7bbf 100644 --- a/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi +++ b/Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi @@ -32,6 +32,9 @@ class Homebrew::Cmd::FetchCmd::Args < Homebrew::CLI::Args sig { returns(T::Boolean) } def casks?; end + sig { returns(T.nilable(String)) } + def concurrency; end + sig { returns(T::Boolean) } def deps?; end diff --git a/Library/Homebrew/test/patch_spec.rb b/Library/Homebrew/test/patch_spec.rb index f9c7b5c5818ee..c546f520a1e80 100644 --- a/Library/Homebrew/test/patch_spec.rb +++ b/Library/Homebrew/test/patch_spec.rb @@ -55,7 +55,7 @@ subject(:patch) { described_class.create(:p2, nil) } context "when the patch is empty" do - it(:resource) { expect(patch.resource).to be_a Resource::PatchResource } + it(:resource) { expect(patch.resource).to be_a Resource::Patch } it { expect(patch.patch_files).to eq(patch.resource.patch_files) } it { expect(patch.patch_files).to eq([]) } end From b6d529dab3f8546c1a20980b651f511489838b50 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 14 Jul 2024 21:03:08 -0400 Subject: [PATCH 03/28] Convert `Downloadable` to a module. --- Library/Homebrew/api/download.rb | 26 ++++++++++++++++++++++++-- Library/Homebrew/cask/download.rb | 4 +++- Library/Homebrew/downloadable.rb | 22 ++++++++++------------ Library/Homebrew/downloadable.rbi | 5 +++++ Library/Homebrew/resource.rb | 3 ++- Library/Homebrew/retryable_download.rb | 4 +++- Library/Homebrew/software_spec.rb | 8 ++++++-- 7 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 Library/Homebrew/downloadable.rbi diff --git a/Library/Homebrew/api/download.rb b/Library/Homebrew/api/download.rb index a13bfe73ca23b..947605805a9a9 100644 --- a/Library/Homebrew/api/download.rb +++ b/Library/Homebrew/api/download.rb @@ -6,13 +6,20 @@ module Homebrew module API class DownloadStrategy < CurlDownloadStrategy + sig { returns(String) } + def name # rubocop:disable Lint/UselessMethodDefinition + super + end + sig { override.returns(Pathname) } def symlink_location cache/name end end - class Download < Downloadable + class Download + include Downloadable + sig { params( url: String, @@ -29,6 +36,21 @@ def initialize(url, checksum, mirrors: [], cache: nil) @cache = cache end + sig { override.returns(API::DownloadStrategy) } + def downloader + T.cast(super, API::DownloadStrategy) + end + + sig { override.returns(String) } + def name + downloader.name + end + + sig { override.returns(String) } + def download_type + "API" + end + sig { override.returns(Pathname) } def cache @cache || super @@ -36,7 +58,7 @@ def cache sig { returns(Pathname) } def symlink_location - T.cast(downloader, API::DownloadStrategy).symlink_location + downloader.symlink_location end end end diff --git a/Library/Homebrew/cask/download.rb b/Library/Homebrew/cask/download.rb index 836825abf538c..eb1d9a7087139 100644 --- a/Library/Homebrew/cask/download.rb +++ b/Library/Homebrew/cask/download.rb @@ -8,7 +8,9 @@ module Cask # A download corresponding to a {Cask}. - class Download < Downloadable + class Download + include Downloadable + include Context attr_reader :cask diff --git a/Library/Homebrew/downloadable.rb b/Library/Homebrew/downloadable.rb index b030c60678f76..d1f6b8a298c2b 100644 --- a/Library/Homebrew/downloadable.rb +++ b/Library/Homebrew/downloadable.rb @@ -5,7 +5,7 @@ require "checksum" require "download_strategy" -class Downloadable +module Downloadable include Context extend T::Helpers @@ -32,7 +32,7 @@ def initialize_dup(other) @version = @version.dup end - sig { override.returns(T.self_type) } + sig { returns(T.self_type) } def freeze @checksum.freeze @mirrors.freeze @@ -40,14 +40,12 @@ def freeze super end - sig { returns(String) } - def name - "" - end + sig { abstract.returns(String) } + def name; end sig { returns(String) } def download_type - T.must(T.must(self.class.name).split("::").last).gsub(/([[:lower:]])([[:upper:]])/, '\1 \2').downcase + T.must(self.class.name&.split("::")&.last).gsub(/([[:lower:]])([[:upper:]])/, '\1 \2').downcase end sig { returns(T::Boolean) } @@ -73,16 +71,16 @@ def version version unless version&.null? end - sig { returns(T.class_of(AbstractDownloadStrategy)) } + sig { overridable.returns(T.class_of(AbstractDownloadStrategy)) } def download_strategy @download_strategy ||= determine_url&.download_strategy end - sig { returns(AbstractDownloadStrategy) } + sig { overridable.returns(AbstractDownloadStrategy) } def downloader @downloader ||= begin primary_url, *mirrors = determine_url_mirrors - raise ArgumentError, "attempted to use a Downloadable without a URL!" if primary_url.blank? + raise ArgumentError, "attempted to use a `Downloadable` without a URL!" if primary_url.blank? download_strategy.new(primary_url, download_name, version, mirrors:, cache:, **T.must(@url).specs) @@ -90,7 +88,7 @@ def downloader end sig { - params( + overridable.params( verify_download_integrity: T::Boolean, timeout: T.nilable(T.any(Integer, Float)), quiet: T::Boolean, @@ -111,7 +109,7 @@ def fetch(verify_download_integrity: true, timeout: nil, quiet: false) download end - sig { params(filename: Pathname).void } + sig { overridable.params(filename: Pathname).void } def verify_download_integrity(filename) if filename.file? ohai "Verifying checksum for '#{filename.basename}'" if verbose? diff --git a/Library/Homebrew/downloadable.rbi b/Library/Homebrew/downloadable.rbi new file mode 100644 index 0000000000000..2b50bad57667c --- /dev/null +++ b/Library/Homebrew/downloadable.rbi @@ -0,0 +1,5 @@ +# typed: strict + +module Downloadable + requires_ancestor { Kernel } +end diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index 59607548de037..3c4e365aa95c0 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -9,7 +9,8 @@ # Resource is the fundamental representation of an external resource. The # primary formula download, along with other declared resources, are instances # of this class. -class Resource < Downloadable +class Resource + include Downloadable include FileUtils include OnSystem::MacOSAndLinux diff --git a/Library/Homebrew/retryable_download.rb b/Library/Homebrew/retryable_download.rb index bd9d9e595c50b..3d389626984b4 100644 --- a/Library/Homebrew/retryable_download.rb +++ b/Library/Homebrew/retryable_download.rb @@ -2,7 +2,9 @@ # frozen_string_literal: true module Homebrew - class RetryableDownload < Downloadable + class RetryableDownload + include Downloadable + sig { returns(Downloadable) } attr_reader :downloadable private :downloadable diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index 305319e88c0bc..81a9b192ee28c 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -15,7 +15,9 @@ require "macos_version" require "extend/on_system" -class SoftwareSpec < Downloadable +class SoftwareSpec + include Downloadable + extend Forwardable include OnSystem::MacOSAndLinux @@ -294,7 +296,9 @@ def verify_download_integrity(_filename) end end -class Bottle < Downloadable +class Bottle + include Downloadable + class Filename attr_reader :name, :version, :tag, :rebuild From f41d2516cede114c94ad3b3c15354fbd9dedee5f Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 14 Jul 2024 22:51:54 -0400 Subject: [PATCH 04/28] Fix type signatures. --- Library/Homebrew/downloadable.rb | 16 +++++++------- Library/Homebrew/resource.rb | 2 +- Library/Homebrew/retryable_download.rb | 30 +++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Library/Homebrew/downloadable.rb b/Library/Homebrew/downloadable.rb index d1f6b8a298c2b..9afb25d55a313 100644 --- a/Library/Homebrew/downloadable.rb +++ b/Library/Homebrew/downloadable.rb @@ -11,13 +11,13 @@ module Downloadable abstract! - sig { returns(T.nilable(URL)) } + sig { overridable.returns(T.nilable(URL)) } attr_reader :url - sig { returns(T.nilable(Checksum)) } + sig { overridable.returns(T.nilable(Checksum)) } attr_reader :checksum - sig { returns(T::Array[String]) } + sig { overridable.returns(T::Array[String]) } attr_reader :mirrors sig { void } @@ -32,7 +32,7 @@ def initialize_dup(other) @version = @version.dup end - sig { returns(T.self_type) } + sig { overridable.returns(T.self_type) } def freeze @checksum.freeze @mirrors.freeze @@ -48,22 +48,22 @@ def download_type T.must(self.class.name&.split("::")&.last).gsub(/([[:lower:]])([[:upper:]])/, '\1 \2').downcase end - sig { returns(T::Boolean) } + sig(:final) { returns(T::Boolean) } def downloaded? cached_download.exist? end - sig { returns(Pathname) } + sig { overridable.returns(Pathname) } def cached_download downloader.cached_location end - sig { void } + sig { overridable.void } def clear_cache downloader.clear_cache end - sig { returns(T.nilable(Version)) } + sig { overridable.returns(T.nilable(Version)) } def version return @version if @version && !@version.null? diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index 3c4e365aa95c0..8471fbca44f53 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -203,7 +203,7 @@ def url(val = nil, **specs) @download_strategy = @url.download_strategy end - sig { params(val: T.nilable(T.any(String, Version))).returns(T.nilable(Version)) } + sig { override.params(val: T.nilable(T.any(String, Version))).returns(T.nilable(Version)) } def version(val = nil) return super() if val.nil? diff --git a/Library/Homebrew/retryable_download.rb b/Library/Homebrew/retryable_download.rb index 3d389626984b4..0f647b88358d3 100644 --- a/Library/Homebrew/retryable_download.rb +++ b/Library/Homebrew/retryable_download.rb @@ -9,6 +9,15 @@ class RetryableDownload attr_reader :downloadable private :downloadable + sig { override.returns(T.nilable(URL)) } + def url = downloadable.url + + sig { override.returns(T.nilable(Checksum)) } + def checksum = downloadable.checksum + + sig { override.returns(T::Array[String]) } + def mirrors = downloadable.mirrors + sig { params(downloadable: Downloadable, tries: Integer).void } def initialize(downloadable, tries: 3) super() @@ -24,12 +33,21 @@ def name = downloadable.name sig { override.returns(String) } def download_type = downloadable.download_type - sig { override.returns(T::Boolean) } - def downloaded? = downloadable.downloaded? - sig { override.returns(Pathname) } def cached_download = downloadable.cached_download + sig { override.void } + def clear_cache = downloadable.clear_cache + + sig { override.returns(T.nilable(Version)) } + def version = downloadable.version + + sig { override.returns(T.class_of(AbstractDownloadStrategy)) } + def download_strategy = downloadable.download_strategy + + sig { override.returns(AbstractDownloadStrategy) } + def downloader = downloadable.downloader + sig { override.params( verify_download_integrity: T::Boolean, @@ -68,5 +86,11 @@ def fetch(verify_download_integrity: true, timeout: nil, quiet: false) downloadable.clear_cache retry end + + sig { override.params(filename: Pathname).void } + def verify_download_integrity(filename) = downloadable.verify_download_integrity(filename) + + sig { override.returns(String) } + def download_name = downloadable.download_name end end From b55528b825b2d9d2ed1596c7c2ad865f432051fc Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 14 Jul 2024 23:15:36 -0400 Subject: [PATCH 05/28] Color status. --- Library/Homebrew/cmd/fetch.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 15eecf70b7ecd..d135692f13f39 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -203,10 +203,10 @@ def run promise.wait! - Whirly.configure stop: "✔︎" + Whirly.configure stop: "#{Tty.green}✔︎#{Tty.reset}" Whirly.stop if args.concurrency rescue ChecksumMismatchError => e - Whirly.configure stop: "✘" + Whirly.configure stop: "#{Tty.red}✘#{Tty.reset}" Whirly.stop if args.concurrency opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" From 601134b0474c44c4a3374fc6ba6d2517431cf041 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sun, 14 Jul 2024 23:22:04 -0400 Subject: [PATCH 06/28] Fix `--force` flag. --- Library/Homebrew/cmd/fetch.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index d135692f13f39..61a7d4cbb21cc 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -223,6 +223,8 @@ def downloads end def fetch_downloadable(downloadable) + downloadable.clear_cache if args.force? + downloads[downloadable] ||= download_queue.enqueue(RetryableDownload.new(downloadable)) end end From b353e9cbf299f96a7304330a982ddccaaee5f1e4 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jul 2024 10:25:25 -0400 Subject: [PATCH 07/28] Don't require everything. --- Library/Homebrew/download_queue.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/download_queue.rb b/Library/Homebrew/download_queue.rb index 18c7e29489d25..29d97d39d05a6 100644 --- a/Library/Homebrew/download_queue.rb +++ b/Library/Homebrew/download_queue.rb @@ -2,7 +2,8 @@ # frozen_string_literal: true require "downloadable" -require "concurrent" +require "concurrent/promise" +require "concurrent/executors" module Homebrew class DownloadQueue From 3a51f55572e8349d6a49112e8497544846f6b0d9 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jul 2024 12:10:42 -0400 Subject: [PATCH 08/28] Move `require`. --- Library/Homebrew/cmd/fetch.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 61a7d4cbb21cc..0a04fa30a2d09 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -6,7 +6,6 @@ require "fetch" require "cask/download" require "retryable_download" -require "whirly" module Homebrew module Cmd @@ -83,6 +82,8 @@ def download_queue sig { override.void } def run + require "whirly" + Formulary.enable_factory_cache! bucket = if args.deps? From 6434533ff51fde2a74f5413551473b8302c8d3c3 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jul 2024 16:31:21 -0400 Subject: [PATCH 09/28] Remove `Whirly` and show concurrent downloads. --- Library/Homebrew/Gemfile | 1 - Library/Homebrew/cmd/fetch.rb | 117 +- .../Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi | 103 -- Library/Homebrew/utils/tty.rb | 29 +- .../3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt | 20 - .../gems/whirly-0.3.0/data/cli-spinners.json | 1415 ----------------- .../data/whirly-static-spinners.json | 274 ---- .../3.3.0/gems/whirly-0.3.0/lib/whirly.rb | 263 --- .../gems/whirly-0.3.0/lib/whirly/spinners.rb | 7 - .../whirly-0.3.0/lib/whirly/spinners/cli.rb | 7 - .../lib/whirly/spinners/whirly.rb | 15 - .../gems/whirly-0.3.0/lib/whirly/version.rb | 5 - 12 files changed, 128 insertions(+), 2128 deletions(-) delete mode 100644 Library/Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi delete mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt delete mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/cli-spinners.json delete mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/whirly-static-spinners.json delete mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly.rb delete mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners.rb delete mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/cli.rb delete mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/whirly.rb delete mode 100644 Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/version.rb diff --git a/Library/Homebrew/Gemfile b/Library/Homebrew/Gemfile index 17f0e703f4489..7849b80fc3fd5 100644 --- a/Library/Homebrew/Gemfile +++ b/Library/Homebrew/Gemfile @@ -84,4 +84,3 @@ gem "plist" gem "ruby-macho" gem "sorbet-runtime" gem "warning" -gem "whirly" diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 0a04fa30a2d09..df9a9172576af 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -80,10 +80,36 @@ def download_queue end end + class Spinner + FRAMES = [ + "◜", + "◠", + "◝", + "◞", + "◡", + "◟", + ].freeze + + sig { void } + def initialize + @start = Time.now + @i = 0 + end + + sig { returns(String) } + def to_s + now = Time.now + if @start + 0.1 < now + @start = now + @i = (@i + 1) % FRAMES.count + end + + FRAMES.fetch(@i) + end + end + sig { override.void } def run - require "whirly" - Formulary.enable_factory_cache! bucket = if args.deps? @@ -194,24 +220,83 @@ def run end end - downloads.each do |downloadable, promise| - message = "#{downloadable.download_type.capitalize} #{downloadable.name}" - if concurrency > 1 - Whirly.start spinner: "arc", status: message - else - puts message + if concurrency == 1 + downloads.each_value do |promise| + promise.wait! + rescue ChecksumMismatchError => e + opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" + Homebrew.failed = true if downloadable.is_a?(Resource::Patch) end + else + + spinner = Spinner.new + + remaining_downloads = downloads.dup + + previous_pending_line_count = 0 + + begin + print Tty.hide_cursor + + output_message = lambda do |downloadable, promise| + status = case promise.state + when :fulfilled + "#{Tty.green}✔︎#{Tty.reset}" + when :rejected + "#{Tty.red}✘#{Tty.reset}" + when :pending + spinner + else + raise promise.state + end - promise.wait! + message = "#{downloadable.download_type.capitalize} #{downloadable.name}" + puts "#{status} #{message}" - Whirly.configure stop: "#{Tty.green}✔︎#{Tty.reset}" - Whirly.stop if args.concurrency - rescue ChecksumMismatchError => e - Whirly.configure stop: "#{Tty.red}✘#{Tty.reset}" - Whirly.stop if args.concurrency + if promise.rejected? && (e = promise.reason).is_a?(ChecksumMismatchError) + opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" + Homebrew.failed = true if downloadable.is_a?(Resource::Patch) + next 2 + end + + 1 + end + + until remaining_downloads.empty? + begin + finished_downloads = {} + + finished_states = [:fulfilled, :rejected] + remaining_downloads.each do |downloadable, promise| + break unless finished_states.include?(promise.state) + + finished_downloads[downloadable] = remaining_downloads.delete(downloadable) + end + + finished_downloads.each do |downloadable, promise| + previous_pending_line_count -= 1 + output_message.call(downloadable, promise) + end + + previous_pending_line_count = 0 + remaining_downloads.each do |downloadable, promise| + break if previous_pending_line_count >= (Tty.height - 1) + + previous_pending_line_count += output_message.call(downloadable, promise) + end - opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" - Homebrew.failed = true if downloadable.is_a?(Resource::Patch) + if previous_pending_line_count.positive? + $stdout.print "\033[#{previous_pending_line_count}A" + $stdout.flush + end + rescue Interrupt + print "\n" * previous_pending_line_count + raise + end + end + ensure + print Tty.show_cursor + end end download_queue.shutdown diff --git a/Library/Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi b/Library/Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi deleted file mode 100644 index f72a0eed60f48..0000000000000 --- a/Library/Homebrew/sorbet/rbi/gems/whirly@0.3.0.rbi +++ /dev/null @@ -1,103 +0,0 @@ -# typed: true - -# DO NOT EDIT MANUALLY -# This is an autogenerated file for types exported from the `whirly` gem. -# Please instead update this file by running `bin/tapioca gem whirly`. - - -# source://whirly//lib/whirly/version.rb#3 -module Whirly - class << self - # save options and preprocess, set defaults if value is still unknown - # - # source://whirly//lib/whirly.rb#114 - def configure(**options); end - - # frames can be generated from enumerables or procs - # - # source://whirly//lib/whirly.rb#85 - def configure_frames(spinner); end - - # set spinner directly or lookup - # - # source://whirly//lib/whirly.rb#55 - def configure_spinner(spinner_option); end - - # @return [Boolean] - # - # source://whirly//lib/whirly.rb#49 - def configured?; end - - # @return [Boolean] - # - # source://whirly//lib/whirly.rb#45 - def enabled?; end - - # source://whirly//lib/whirly.rb#240 - def initialize_color; end - - # source://whirly//lib/whirly.rb#249 - def next_color; end - - # Returns the value of attribute options. - # - # source://whirly//lib/whirly.rb#43 - def options; end - - # source://whirly//lib/whirly.rb#215 - def render(next_frame = T.unsafe(nil)); end - - # source://whirly//lib/whirly.rb#225 - def render_prefix; end - - # source://whirly//lib/whirly.rb#233 - def render_suffix; end - - # source://whirly//lib/whirly.rb#194 - def reset; end - - # source://whirly//lib/whirly.rb#132 - def start(**options); end - - # Returns the value of attribute status. - # - # source://whirly//lib/whirly.rb#42 - def status; end - - # Sets the attribute status - # - # @param value the value to set the attribute status to. - # - # source://whirly//lib/whirly.rb#42 - def status=(_arg0); end - - # source://whirly//lib/whirly.rb#180 - def stop(stop_frame = T.unsafe(nil)); end - - # - - - - # - # source://whirly//lib/whirly.rb#203 - def unrender; end - end -end - -# source://whirly//lib/whirly.rb#14 -Whirly::CLI_COMMANDS = T.let(T.unsafe(nil), Hash) - -# source://whirly//lib/whirly.rb#19 -Whirly::DEFAULT_OPTIONS = T.let(T.unsafe(nil), Hash) - -# source://whirly//lib/whirly.rb#35 -Whirly::SOFT_DEFAULT_OPTIONS = T.let(T.unsafe(nil), Hash) - -# source://whirly//lib/whirly/spinners.rb#2 -module Whirly::Spinners; end - -# source://whirly//lib/whirly/spinners/cli.rb#5 -Whirly::Spinners::CLI = T.let(T.unsafe(nil), Hash) - -# source://whirly//lib/whirly/spinners/whirly.rb#5 -Whirly::Spinners::WHIRLY = T.let(T.unsafe(nil), Hash) - -# source://whirly//lib/whirly/version.rb#4 -Whirly::VERSION = T.let(T.unsafe(nil), String) diff --git a/Library/Homebrew/utils/tty.rb b/Library/Homebrew/utils/tty.rb index f1ebba8a89615..c10720aa4e1f1 100644 --- a/Library/Homebrew/utils/tty.rb +++ b/Library/Homebrew/utils/tty.rb @@ -51,11 +51,36 @@ def strip_ansi(string) string.gsub(/\033\[\d+(;\d+)*m/, "") end + sig { returns(String) } + def hide_cursor + "\033[?25l" + end + + sig { returns(String) } + def show_cursor + "\033[?25h" + end + + sig { returns(T.nilable([Integer, Integer])) } + def size + `/bin/stty size 2>/dev/null`.split&.map(&:to_i) + end + + sig { returns(Integer) } + def height + @height ||= begin + height, = size + height, = `/usr/bin/tput lines 2>/dev/null`.split if height.zero? + height ||= 40 + height.to_i + end + end + sig { returns(Integer) } def width @width ||= begin - _, width = `/bin/stty size 2>/dev/null`.split - width, = `/usr/bin/tput cols 2>/dev/null`.split if width.to_i.zero? + _, width = size + width, = `/usr/bin/tput cols 2>/dev/null`.split if width.zero? width ||= 80 width.to_i end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt deleted file mode 100644 index bfe58e510bd1e..0000000000000 --- a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/MIT-LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2016 Jan Lelis, https://janlelis.com - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/cli-spinners.json b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/cli-spinners.json deleted file mode 100644 index 89b0edba1c483..0000000000000 --- a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/cli-spinners.json +++ /dev/null @@ -1,1415 +0,0 @@ -{ - "dots": { - "interval": 80, - "frames": [ - "⠋", - "⠙", - "⠹", - "⠸", - "⠼", - "⠴", - "⠦", - "⠧", - "⠇", - "⠏" - ] - }, - "dots2": { - "interval": 80, - "frames": [ - "⣾", - "⣽", - "⣻", - "⢿", - "⡿", - "⣟", - "⣯", - "⣷" - ] - }, - "dots3": { - "interval": 80, - "frames": [ - "⠋", - "⠙", - "⠚", - "⠞", - "⠖", - "⠦", - "⠴", - "⠲", - "⠳", - "⠓" - ] - }, - "dots4": { - "interval": 80, - "frames": [ - "⠄", - "⠆", - "⠇", - "⠋", - "⠙", - "⠸", - "⠰", - "⠠", - "⠰", - "⠸", - "⠙", - "⠋", - "⠇", - "⠆" - ] - }, - "dots5": { - "interval": 80, - "frames": [ - "⠋", - "⠙", - "⠚", - "⠒", - "⠂", - "⠂", - "⠒", - "⠲", - "⠴", - "⠦", - "⠖", - "⠒", - "⠐", - "⠐", - "⠒", - "⠓", - "⠋" - ] - }, - "dots6": { - "interval": 80, - "frames": [ - "⠁", - "⠉", - "⠙", - "⠚", - "⠒", - "⠂", - "⠂", - "⠒", - "⠲", - "⠴", - "⠤", - "⠄", - "⠄", - "⠤", - "⠴", - "⠲", - "⠒", - "⠂", - "⠂", - "⠒", - "⠚", - "⠙", - "⠉", - "⠁" - ] - }, - "dots7": { - "interval": 80, - "frames": [ - "⠈", - "⠉", - "⠋", - "⠓", - "⠒", - "⠐", - "⠐", - "⠒", - "⠖", - "⠦", - "⠤", - "⠠", - "⠠", - "⠤", - "⠦", - "⠖", - "⠒", - "⠐", - "⠐", - "⠒", - "⠓", - "⠋", - "⠉", - "⠈" - ] - }, - "dots8": { - "interval": 80, - "frames": [ - "⠁", - "⠁", - "⠉", - "⠙", - "⠚", - "⠒", - "⠂", - "⠂", - "⠒", - "⠲", - "⠴", - "⠤", - "⠄", - "⠄", - "⠤", - "⠠", - "⠠", - "⠤", - "⠦", - "⠖", - "⠒", - "⠐", - "⠐", - "⠒", - "⠓", - "⠋", - "⠉", - "⠈", - "⠈" - ] - }, - "dots9": { - "interval": 80, - "frames": [ - "⢹", - "⢺", - "⢼", - "⣸", - "⣇", - "⡧", - "⡗", - "⡏" - ] - }, - "dots10": { - "interval": 80, - "frames": [ - "⢄", - "⢂", - "⢁", - "⡁", - "⡈", - "⡐", - "⡠" - ] - }, - "dots11": { - "interval": 100, - "frames": [ - "⠁", - "⠂", - "⠄", - "⡀", - "⢀", - "⠠", - "⠐", - "⠈" - ] - }, - "dots12": { - "interval": 80, - "frames": [ - "⢀⠀", - "⡀⠀", - "⠄⠀", - "⢂⠀", - "⡂⠀", - "⠅⠀", - "⢃⠀", - "⡃⠀", - "⠍⠀", - "⢋⠀", - "⡋⠀", - "⠍⠁", - "⢋⠁", - "⡋⠁", - "⠍⠉", - "⠋⠉", - "⠋⠉", - "⠉⠙", - "⠉⠙", - "⠉⠩", - "⠈⢙", - "⠈⡙", - "⢈⠩", - "⡀⢙", - "⠄⡙", - "⢂⠩", - "⡂⢘", - "⠅⡘", - "⢃⠨", - "⡃⢐", - "⠍⡐", - "⢋⠠", - "⡋⢀", - "⠍⡁", - "⢋⠁", - "⡋⠁", - "⠍⠉", - "⠋⠉", - "⠋⠉", - "⠉⠙", - "⠉⠙", - "⠉⠩", - "⠈⢙", - "⠈⡙", - "⠈⠩", - "⠀⢙", - "⠀⡙", - "⠀⠩", - "⠀⢘", - "⠀⡘", - "⠀⠨", - "⠀⢐", - "⠀⡐", - "⠀⠠", - "⠀⢀", - "⠀⡀" - ] - }, - "dots8Bit": { - "interval": 80, - "frames": [ - "⠀", - "⠁", - "⠂", - "⠃", - "⠄", - "⠅", - "⠆", - "⠇", - "⡀", - "⡁", - "⡂", - "⡃", - "⡄", - "⡅", - "⡆", - "⡇", - "⠈", - "⠉", - "⠊", - "⠋", - "⠌", - "⠍", - "⠎", - "⠏", - "⡈", - "⡉", - "⡊", - "⡋", - "⡌", - "⡍", - "⡎", - "⡏", - "⠐", - "⠑", - "⠒", - "⠓", - "⠔", - "⠕", - "⠖", - "⠗", - "⡐", - "⡑", - "⡒", - "⡓", - "⡔", - "⡕", - "⡖", - "⡗", - "⠘", - "⠙", - "⠚", - "⠛", - "⠜", - "⠝", - "⠞", - "⠟", - "⡘", - "⡙", - "⡚", - "⡛", - "⡜", - "⡝", - "⡞", - "⡟", - "⠠", - "⠡", - "⠢", - "⠣", - "⠤", - "⠥", - "⠦", - "⠧", - "⡠", - "⡡", - "⡢", - "⡣", - "⡤", - "⡥", - "⡦", - "⡧", - "⠨", - "⠩", - "⠪", - "⠫", - "⠬", - "⠭", - "⠮", - "⠯", - "⡨", - "⡩", - "⡪", - "⡫", - "⡬", - "⡭", - "⡮", - "⡯", - "⠰", - "⠱", - "⠲", - "⠳", - "⠴", - "⠵", - "⠶", - "⠷", - "⡰", - "⡱", - "⡲", - "⡳", - "⡴", - "⡵", - "⡶", - "⡷", - "⠸", - "⠹", - "⠺", - "⠻", - "⠼", - "⠽", - "⠾", - "⠿", - "⡸", - "⡹", - "⡺", - "⡻", - "⡼", - "⡽", - "⡾", - "⡿", - "⢀", - "⢁", - "⢂", - "⢃", - "⢄", - "⢅", - "⢆", - "⢇", - "⣀", - "⣁", - "⣂", - "⣃", - "⣄", - "⣅", - "⣆", - "⣇", - "⢈", - "⢉", - "⢊", - "⢋", - "⢌", - "⢍", - "⢎", - "⢏", - "⣈", - "⣉", - "⣊", - "⣋", - "⣌", - "⣍", - "⣎", - "⣏", - "⢐", - "⢑", - "⢒", - "⢓", - "⢔", - "⢕", - "⢖", - "⢗", - "⣐", - "⣑", - "⣒", - "⣓", - "⣔", - "⣕", - "⣖", - "⣗", - "⢘", - "⢙", - "⢚", - "⢛", - "⢜", - "⢝", - "⢞", - "⢟", - "⣘", - "⣙", - "⣚", - "⣛", - "⣜", - "⣝", - "⣞", - "⣟", - "⢠", - "⢡", - "⢢", - "⢣", - "⢤", - "⢥", - "⢦", - "⢧", - "⣠", - "⣡", - "⣢", - "⣣", - "⣤", - "⣥", - "⣦", - "⣧", - "⢨", - "⢩", - "⢪", - "⢫", - "⢬", - "⢭", - "⢮", - "⢯", - "⣨", - "⣩", - "⣪", - "⣫", - "⣬", - "⣭", - "⣮", - "⣯", - "⢰", - "⢱", - "⢲", - "⢳", - "⢴", - "⢵", - "⢶", - "⢷", - "⣰", - "⣱", - "⣲", - "⣳", - "⣴", - "⣵", - "⣶", - "⣷", - "⢸", - "⢹", - "⢺", - "⢻", - "⢼", - "⢽", - "⢾", - "⢿", - "⣸", - "⣹", - "⣺", - "⣻", - "⣼", - "⣽", - "⣾", - "⣿" - ] - }, - "line": { - "interval": 130, - "frames": [ - "-", - "\\", - "|", - "/" - ] - }, - "line2": { - "interval": 100, - "frames": [ - "⠂", - "-", - "–", - "—", - "–", - "-" - ] - }, - "pipe": { - "interval": 100, - "frames": [ - "┤", - "┘", - "┴", - "└", - "├", - "┌", - "┬", - "┐" - ] - }, - "simpleDots": { - "interval": 400, - "frames": [ - ". ", - ".. ", - "...", - " " - ] - }, - "simpleDotsScrolling": { - "interval": 200, - "frames": [ - ". ", - ".. ", - "...", - " ..", - " .", - " " - ] - }, - "star": { - "interval": 70, - "frames": [ - "✶", - "✸", - "✹", - "✺", - "✹", - "✷" - ] - }, - "star2": { - "interval": 80, - "frames": [ - "+", - "x", - "*" - ] - }, - "flip": { - "interval": 70, - "frames": [ - "_", - "_", - "_", - "-", - "`", - "`", - "'", - "´", - "-", - "_", - "_", - "_" - ] - }, - "hamburger": { - "interval": 100, - "frames": [ - "☱", - "☲", - "☴" - ] - }, - "growVertical": { - "interval": 120, - "frames": [ - "▁", - "▃", - "▄", - "▅", - "▆", - "▇", - "▆", - "▅", - "▄", - "▃" - ] - }, - "growHorizontal": { - "interval": 120, - "frames": [ - "▏", - "▎", - "▍", - "▌", - "▋", - "▊", - "▉", - "▊", - "▋", - "▌", - "▍", - "▎" - ] - }, - "balloon": { - "interval": 140, - "frames": [ - " ", - ".", - "o", - "O", - "@", - "*", - " " - ] - }, - "balloon2": { - "interval": 120, - "frames": [ - ".", - "o", - "O", - "°", - "O", - "o", - "." - ] - }, - "noise": { - "interval": 100, - "frames": [ - "▓", - "▒", - "░" - ] - }, - "bounce": { - "interval": 120, - "frames": [ - "⠁", - "⠂", - "⠄", - "⠂" - ] - }, - "boxBounce": { - "interval": 120, - "frames": [ - "▖", - "▘", - "▝", - "▗" - ] - }, - "boxBounce2": { - "interval": 100, - "frames": [ - "▌", - "▀", - "▐", - "▄" - ] - }, - "triangle": { - "interval": 50, - "frames": [ - "◢", - "◣", - "◤", - "◥" - ] - }, - "arc": { - "interval": 100, - "frames": [ - "◜", - "◠", - "◝", - "◞", - "◡", - "◟" - ] - }, - "circle": { - "interval": 120, - "frames": [ - "◡", - "⊙", - "◠" - ] - }, - "squareCorners": { - "interval": 180, - "frames": [ - "◰", - "◳", - "◲", - "◱" - ] - }, - "circleQuarters": { - "interval": 120, - "frames": [ - "◴", - "◷", - "◶", - "◵" - ] - }, - "circleHalves": { - "interval": 50, - "frames": [ - "◐", - "◓", - "◑", - "◒" - ] - }, - "squish": { - "interval": 100, - "frames": [ - "╫", - "╪" - ] - }, - "toggle": { - "interval": 250, - "frames": [ - "⊶", - "⊷" - ] - }, - "toggle2": { - "interval": 80, - "frames": [ - "▫", - "▪" - ] - }, - "toggle3": { - "interval": 120, - "frames": [ - "□", - "■" - ] - }, - "toggle4": { - "interval": 100, - "frames": [ - "■", - "□", - "▪", - "▫" - ] - }, - "toggle5": { - "interval": 100, - "frames": [ - "▮", - "▯" - ] - }, - "toggle6": { - "interval": 300, - "frames": [ - "ဝ", - "၀" - ] - }, - "toggle7": { - "interval": 80, - "frames": [ - "⦾", - "⦿" - ] - }, - "toggle8": { - "interval": 100, - "frames": [ - "◍", - "◌" - ] - }, - "toggle9": { - "interval": 100, - "frames": [ - "◉", - "◎" - ] - }, - "toggle10": { - "interval": 100, - "frames": [ - "㊂", - "㊀", - "㊁" - ] - }, - "toggle11": { - "interval": 50, - "frames": [ - "⧇", - "⧆" - ] - }, - "toggle12": { - "interval": 120, - "frames": [ - "☗", - "☖" - ] - }, - "toggle13": { - "interval": 80, - "frames": [ - "=", - "*", - "-" - ] - }, - "arrow": { - "interval": 100, - "frames": [ - "←", - "↖", - "↑", - "↗", - "→", - "↘", - "↓", - "↙" - ] - }, - "arrow2": { - "interval": 80, - "frames": [ - "⬆️ ", - "↗️ ", - "➡️ ", - "↘️ ", - "⬇️ ", - "↙️ ", - "⬅️ ", - "↖️ " - ] - }, - "arrow3": { - "interval": 120, - "frames": [ - "▹▹▹▹▹", - "▸▹▹▹▹", - "▹▸▹▹▹", - "▹▹▸▹▹", - "▹▹▹▸▹", - "▹▹▹▹▸" - ] - }, - "bouncingBar": { - "interval": 80, - "frames": [ - "[ ]", - "[= ]", - "[== ]", - "[=== ]", - "[ ===]", - "[ ==]", - "[ =]", - "[ ]", - "[ =]", - "[ ==]", - "[ ===]", - "[====]", - "[=== ]", - "[== ]", - "[= ]" - ] - }, - "bouncingBall": { - "interval": 80, - "frames": [ - "( ● )", - "( ● )", - "( ● )", - "( ● )", - "( ●)", - "( ● )", - "( ● )", - "( ● )", - "( ● )", - "(● )" - ] - }, - "smiley": { - "interval": 200, - "frames": [ - "😄 ", - "😝 " - ] - }, - "monkey": { - "interval": 300, - "frames": [ - "🙈 ", - "🙈 ", - "🙉 ", - "🙊 " - ] - }, - "hearts": { - "interval": 100, - "frames": [ - "💛 ", - "💙 ", - "💜 ", - "💚 ", - "❤️ " - ] - }, - "clock": { - "interval": 100, - "frames": [ - "🕛 ", - "🕐 ", - "🕑 ", - "🕒 ", - "🕓 ", - "🕔 ", - "🕕 ", - "🕖 ", - "🕗 ", - "🕘 ", - "🕙 ", - "🕚 " - ] - }, - "earth": { - "interval": 180, - "frames": [ - "🌍 ", - "🌎 ", - "🌏 " - ] - }, - "material": { - "interval": 17, - "frames": [ - "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", - "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", - "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", - "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", - "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", - "██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁", - "███████▁▁▁▁▁▁▁▁▁▁▁▁▁", - "████████▁▁▁▁▁▁▁▁▁▁▁▁", - "█████████▁▁▁▁▁▁▁▁▁▁▁", - "█████████▁▁▁▁▁▁▁▁▁▁▁", - "██████████▁▁▁▁▁▁▁▁▁▁", - "███████████▁▁▁▁▁▁▁▁▁", - "█████████████▁▁▁▁▁▁▁", - "██████████████▁▁▁▁▁▁", - "██████████████▁▁▁▁▁▁", - "▁██████████████▁▁▁▁▁", - "▁██████████████▁▁▁▁▁", - "▁██████████████▁▁▁▁▁", - "▁▁██████████████▁▁▁▁", - "▁▁▁██████████████▁▁▁", - "▁▁▁▁█████████████▁▁▁", - "▁▁▁▁██████████████▁▁", - "▁▁▁▁██████████████▁▁", - "▁▁▁▁▁██████████████▁", - "▁▁▁▁▁██████████████▁", - "▁▁▁▁▁██████████████▁", - "▁▁▁▁▁▁██████████████", - "▁▁▁▁▁▁██████████████", - "▁▁▁▁▁▁▁█████████████", - "▁▁▁▁▁▁▁█████████████", - "▁▁▁▁▁▁▁▁████████████", - "▁▁▁▁▁▁▁▁████████████", - "▁▁▁▁▁▁▁▁▁███████████", - "▁▁▁▁▁▁▁▁▁███████████", - "▁▁▁▁▁▁▁▁▁▁██████████", - "▁▁▁▁▁▁▁▁▁▁██████████", - "▁▁▁▁▁▁▁▁▁▁▁▁████████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", - "█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", - "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", - "██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", - "███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", - "████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", - "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", - "█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", - "██████▁▁▁▁▁▁▁▁▁▁▁▁▁█", - "████████▁▁▁▁▁▁▁▁▁▁▁▁", - "█████████▁▁▁▁▁▁▁▁▁▁▁", - "█████████▁▁▁▁▁▁▁▁▁▁▁", - "█████████▁▁▁▁▁▁▁▁▁▁▁", - "█████████▁▁▁▁▁▁▁▁▁▁▁", - "███████████▁▁▁▁▁▁▁▁▁", - "████████████▁▁▁▁▁▁▁▁", - "████████████▁▁▁▁▁▁▁▁", - "██████████████▁▁▁▁▁▁", - "██████████████▁▁▁▁▁▁", - "▁██████████████▁▁▁▁▁", - "▁██████████████▁▁▁▁▁", - "▁▁▁█████████████▁▁▁▁", - "▁▁▁▁▁████████████▁▁▁", - "▁▁▁▁▁████████████▁▁▁", - "▁▁▁▁▁▁███████████▁▁▁", - "▁▁▁▁▁▁▁▁█████████▁▁▁", - "▁▁▁▁▁▁▁▁█████████▁▁▁", - "▁▁▁▁▁▁▁▁▁█████████▁▁", - "▁▁▁▁▁▁▁▁▁█████████▁▁", - "▁▁▁▁▁▁▁▁▁▁█████████▁", - "▁▁▁▁▁▁▁▁▁▁▁████████▁", - "▁▁▁▁▁▁▁▁▁▁▁████████▁", - "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", - "▁▁▁▁▁▁▁▁▁▁▁▁███████▁", - "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁███████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁", - "▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁" - ] - }, - "moon": { - "interval": 80, - "frames": [ - "🌑 ", - "🌒 ", - "🌓 ", - "🌔 ", - "🌕 ", - "🌖 ", - "🌗 ", - "🌘 " - ] - }, - "runner": { - "interval": 140, - "frames": [ - "🚶 ", - "🏃 " - ] - }, - "pong": { - "interval": 80, - "frames": [ - "▐⠂ ▌", - "▐⠈ ▌", - "▐ ⠂ ▌", - "▐ ⠠ ▌", - "▐ ⡀ ▌", - "▐ ⠠ ▌", - "▐ ⠂ ▌", - "▐ ⠈ ▌", - "▐ ⠂ ▌", - "▐ ⠠ ▌", - "▐ ⡀ ▌", - "▐ ⠠ ▌", - "▐ ⠂ ▌", - "▐ ⠈ ▌", - "▐ ⠂▌", - "▐ ⠠▌", - "▐ ⡀▌", - "▐ ⠠ ▌", - "▐ ⠂ ▌", - "▐ ⠈ ▌", - "▐ ⠂ ▌", - "▐ ⠠ ▌", - "▐ ⡀ ▌", - "▐ ⠠ ▌", - "▐ ⠂ ▌", - "▐ ⠈ ▌", - "▐ ⠂ ▌", - "▐ ⠠ ▌", - "▐ ⡀ ▌", - "▐⠠ ▌" - ] - }, - "shark": { - "interval": 120, - "frames": [ - "▐|\\____________▌", - "▐_|\\___________▌", - "▐__|\\__________▌", - "▐___|\\_________▌", - "▐____|\\________▌", - "▐_____|\\_______▌", - "▐______|\\______▌", - "▐_______|\\_____▌", - "▐________|\\____▌", - "▐_________|\\___▌", - "▐__________|\\__▌", - "▐___________|\\_▌", - "▐____________|\\▌", - "▐____________/|▌", - "▐___________/|_▌", - "▐__________/|__▌", - "▐_________/|___▌", - "▐________/|____▌", - "▐_______/|_____▌", - "▐______/|______▌", - "▐_____/|_______▌", - "▐____/|________▌", - "▐___/|_________▌", - "▐__/|__________▌", - "▐_/|___________▌", - "▐/|____________▌" - ] - }, - "dqpb": { - "interval": 100, - "frames": [ - "d", - "q", - "p", - "b" - ] - }, - "weather": { - "interval": 100, - "frames": [ - "☀️ ", - "☀️ ", - "☀️ ", - "🌤 ", - "⛅️ ", - "🌥 ", - "☁️ ", - "🌧 ", - "🌨 ", - "🌧 ", - "🌨 ", - "🌧 ", - "🌨 ", - "⛈ ", - "🌨 ", - "🌧 ", - "🌨 ", - "☁️ ", - "🌥 ", - "⛅️ ", - "🌤 ", - "☀️ ", - "☀️ " - ] - }, - "christmas": { - "interval": 400, - "frames": [ - "🌲", - "🎄" - ] - }, - "grenade": { - "interval": 80, - "frames": [ - "، ", - "′ ", - " ´ ", - " ‾ ", - " ⸌", - " ⸊", - " |", - " ⁎", - " ⁕", - " ෴ ", - " ⁓", - " ", - " ", - " " - ] - }, - "point": { - "interval": 125, - "frames": [ - "∙∙∙", - "●∙∙", - "∙●∙", - "∙∙●", - "∙∙∙" - ] - }, - "layer": { - "interval": 150, - "frames": [ - "-", - "=", - "≡" - ] - }, - "betaWave": { - "interval": 80, - "frames": [ - "ρββββββ", - "βρβββββ", - "ββρββββ", - "βββρβββ", - "ββββρββ", - "βββββρβ", - "ββββββρ" - ] - }, - "fingerDance": { - "interval": 160, - "frames": [ - "🤘 ", - "🤟 ", - "🖖 ", - "✋ ", - "🤚 ", - "👆 " - ] - }, - "fistBump": { - "interval": 80, - "frames": [ - "🤜\u3000\u3000\u3000\u3000🤛 ", - "🤜\u3000\u3000\u3000\u3000🤛 ", - "🤜\u3000\u3000\u3000\u3000🤛 ", - "\u3000🤜\u3000\u3000🤛\u3000 ", - "\u3000\u3000🤜🤛\u3000\u3000 ", - "\u3000🤜✨🤛\u3000\u3000 ", - "🤜\u3000✨\u3000🤛\u3000 " - ] - }, - "soccerHeader": { - "interval": 80, - "frames": [ - " 🧑⚽️ 🧑 ", - "🧑 ⚽️ 🧑 ", - "🧑 ⚽️ 🧑 ", - "🧑 ⚽️ 🧑 ", - "🧑 ⚽️ 🧑 ", - "🧑 ⚽️ 🧑 ", - "🧑 ⚽️🧑 ", - "🧑 ⚽️ 🧑 ", - "🧑 ⚽️ 🧑 ", - "🧑 ⚽️ 🧑 ", - "🧑 ⚽️ 🧑 ", - "🧑 ⚽️ 🧑 " - ] - }, - "mindblown": { - "interval": 160, - "frames": [ - "😐 ", - "😐 ", - "😮 ", - "😮 ", - "😦 ", - "😦 ", - "😧 ", - "😧 ", - "🤯 ", - "💥 ", - "✨ ", - "\u3000 ", - "\u3000 ", - "\u3000 " - ] - }, - "speaker": { - "interval": 160, - "frames": [ - "🔈 ", - "🔉 ", - "🔊 ", - "🔉 " - ] - }, - "orangePulse": { - "interval": 100, - "frames": [ - "🔸 ", - "🔶 ", - "🟠 ", - "🟠 ", - "🔶 " - ] - }, - "bluePulse": { - "interval": 100, - "frames": [ - "🔹 ", - "🔷 ", - "🔵 ", - "🔵 ", - "🔷 " - ] - }, - "orangeBluePulse": { - "interval": 100, - "frames": [ - "🔸 ", - "🔶 ", - "🟠 ", - "🟠 ", - "🔶 ", - "🔹 ", - "🔷 ", - "🔵 ", - "🔵 ", - "🔷 " - ] - }, - "timeTravel": { - "interval": 100, - "frames": [ - "🕛 ", - "🕚 ", - "🕙 ", - "🕘 ", - "🕗 ", - "🕖 ", - "🕕 ", - "🕔 ", - "🕓 ", - "🕒 ", - "🕑 ", - "🕐 " - ] - }, - "aesthetic": { - "interval": 80, - "frames": [ - "▰▱▱▱▱▱▱", - "▰▰▱▱▱▱▱", - "▰▰▰▱▱▱▱", - "▰▰▰▰▱▱▱", - "▰▰▰▰▰▱▱", - "▰▰▰▰▰▰▱", - "▰▰▰▰▰▰▰", - "▰▱▱▱▱▱▱" - ] - } -} diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/whirly-static-spinners.json b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/whirly-static-spinners.json deleted file mode 100644 index 3c99177d155fc..0000000000000 --- a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/data/whirly-static-spinners.json +++ /dev/null @@ -1,274 +0,0 @@ -{ - "roman_numerals": { - "interval": 90, - "mode": "swing", - "frames": [ - "Ⅰ", - "Ⅱ", - "Ⅲ", - "Ⅳ", - "Ⅴ", - "Ⅵ", - "Ⅶ", - "Ⅷ", - "Ⅸ", - "Ⅹ" - ] - }, - "double_mark": { - "interval": 120, - "mode": "random", - "frames": [ - "⁇", - "⁈", - "⁉", - "‼" - ] - }, - "heart_exclamation": { - "interval": 45, - "frames": [ - "❢", - "❣" - ] - }, - "pencil": { - "interval": 200, - "frames": [ - "✏", - "✎" - ] - }, - "bars": { - "interval": 80, - "mode": "swing", - "frames": [ - "𝍠", - "𝍡", - "𝍢", - "𝍣", - "𝍤" - ] - }, - "dice": { - "interval": 100, - "mode": "random", - "frames": [ - "⚀", - "⚁", - "⚂", - "⚃", - "⚄", - "⚅" - ] - }, - "hanoi": { - "interval": 150, - "mode": "swing", - "frames": [ - "𝍥", - "𝍦", - "𝍧", - "𝍨" - ] - }, - "vertical_bars": { - "interval": 80, - "mode": "swing", - "frames": [ - "𝍩", - "𝍪", - "𝍫", - "𝍬", - "𝍭" - ] - }, - "whirly": { - "interval": 200, - "mode": "random", - "frames": [ - "😀", - "😁", - "😂", - "😃", - "😄", - "😅", - "😆", - "😇", - "😈", - "😉", - "😊", - "😋", - "😌", - "😍", - "😎", - "😏", - "😐", - "😑", - "😒", - "😓", - "😔", - "😕", - "😖", - "😗", - "😘", - "😙", - "😚", - "😛", - "😜", - "😝", - "😞", - "😟", - "😠", - "😡", - "😢", - "😣", - "😤", - "😥", - "😦", - "😧", - "😨", - "😩", - "😪", - "😫", - "😬", - "😭", - "😮", - "😯", - "😰", - "😱", - "😲", - "😳", - "😴", - "😵", - "😶", - "🙁", - "🙂", - "🙃", - "🙄", - "😷", - "🤐", - "🤑", - "🤒", - "🤓", - "🤔", - "🤕", - "🤖", - "🤗" - ] - }, - "cat": { - "interval": 200, - "mode": "random", - "frames": [ - "😸", - "😹", - "😺", - "😻", - "😼", - "😽", - "😾", - "😿", - "🙀" - ] - }, - "card": { - "interval": 90, - "stop": "🂠", - "frames": [ - "🃁", "🃂", "🃃", "🃄", "🃅", "🃆", "🃇", "🃈", "🃉", "🃊", "🃋", "🃌", "🃍", "🃎", - "🂱", "🂲", "🂳", "🂴", "🂵", "🂶", "🂷", "🂸", "🂹", "🂺", "🂻", "🂼", "🂽", "🂾", - "🂡", "🂢", "🂣", "🂤", "🂥", "🂦", "🂧", "🂨", "🂩", "🂪", "🂫", "🂬", "🂭", "🂮", - "🃑", "🃒", "🃓", "🃔", "🃕", "🃖", "🃗", "🃘", "🃙", "🃚", "🃛", "🃜", "🃝", "🃞" - ] - }, - "cloud": { - "interval": 140, - "frames": [ - "🌥", - "🌦", - "🌧", - "🌨", - "🌩", - "🌪" - ] - }, - "photo": { - "interval": 200, - "frames": [ - "📷", - "📸" - ] - }, - "banknote": { - "interval": 100, - "frames": [ - "💴", - "💵", - "💶", - "💷" - ] - }, - "white_square": { - "interval": 100, - "mode": "swing", - "frames": [ - "🞓", - "🞒", - "🞑", - "🞐", - "🞏", - "🞎", - "🞔" - ] - }, - "xberg": { - "interval": 150, - "mode": "random", - "frames": [ - "⨯", - "⛰", - "⛰", - "⛰", - "⛰", - "⛰", - "⛰" - ] - }, - "circled_letter": { - "interval": 120, - "mode": "random", - "frames": [ - "Ⓐ", "Ⓑ", "Ⓒ", "Ⓓ", "Ⓔ", "Ⓕ", "Ⓖ", "Ⓗ", "Ⓘ", - "Ⓙ", "Ⓚ", "Ⓛ", "Ⓜ", "Ⓝ", "Ⓞ", "Ⓟ", "Ⓠ", "Ⓡ", - "Ⓢ", "Ⓣ", "Ⓤ", "Ⓥ", "Ⓦ", "Ⓧ", "Ⓨ", "Ⓩ" - ] - }, - "circled_number": { - "interval": 120, - "mode": "random", - "frames": [ - "①", "②", "③", "④", "⑤", "⑥", "⑦", "⑧", "⑨" - ] - }, - "letter_with_parens": { - "interval": 150, - "mode": "random", - "frames": [ - "🄐", "🄑", "🄒", "🄓", "🄔", "🄕", "🄖", "🄗", "🄘", - "🄙", "🄚", "🄛", "🄜", "🄝", "🄞", "🄟", "🄠", "🄡", - "🄢", "🄣", "🄤", "🄥", "🄦", "🄧", "🄨", "🄩" - ] - }, - "starlike": { - "interval": 120, - "mode": "random", - "frames": [ - "✩", "✪", "✫", "✬", "✭", "✮", "✯", "✰", - "✱", "✲", "✳", "✴", "✵", "✶", "✷", "✸", - "✹", "✺", "✻", "✼", "✽", "✾", "✿", "❀", - "❁", "❂", "❃", "❄", "❅", "❆", "❇", "❈", - "❉", "❊" - ] - } -} diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly.rb deleted file mode 100644 index 5106fc7c06e5e..0000000000000 --- a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly.rb +++ /dev/null @@ -1,263 +0,0 @@ -require_relative "whirly/version" -require_relative "whirly/spinners" - -require "unicode/display_width" - -begin - require "paint" -rescue LoadError -end - -module Whirly - @configured = false - - CLI_COMMANDS = { - hide_cursor: "\x1b[?25l", - show_cursor: "\x1b[?25h", - }.freeze - - DEFAULT_OPTIONS = { - ambiguous_character_width: 1, - ansi_escape_mode: "restore", - append_newline: true, - color: !!defined?(Paint), - color_change_rate: 30, - hide_cursor: true, - non_tty: false, - position: "normal", - remove_after_stop: false, - spinner: "whirly", - spinner_packs: [:whirly, :cli], - status: nil, - stream: $stdout, - }.freeze - - SOFT_DEFAULT_OPTIONS = { - interval: 100, - mode: "linear", - stop: nil, - }.freeze - - class << self - attr_accessor :status - attr_reader :options - - def enabled? - !!(defined?(@enabled) && @enabled) - end - - def configured? - !!(@configured) - end - end - - # set spinner directly or lookup - def self.configure_spinner(spinner_option) - case spinner_option - when Hash - spinner = spinner_option.dup - when Enumerable - spinner = { "frames" => spinner_option.dup } - when Proc - spinner = { "proc" => spinner_option.dup } - else - spinner = nil - catch(:found){ - @options[:spinner_packs].each{ |spinner_pack| - spinners = Whirly::Spinners.const_get(spinner_pack.to_s.upcase) - if spinners[spinner_option] - spinner = spinners[spinner_option].dup - throw(:found) - end - } - } - end - - # validate spinner - if !spinner || (!spinner["frames"] && !spinner["proc"]) - raise(ArgumentError, "Whirly: Invalid spinner given") - end - - spinner - end - - # frames can be generated from enumerables or procs - def self.configure_frames(spinner) - if spinner["frames"] - case spinner["mode"] - when "swing" - frames = (spinner["frames"].to_a + spinner["frames"].to_a[1..-2].reverse).cycle - when "random" - frame_pool = spinner["frames"].to_a - frames = ->(){ frame_pool.sample } - when "reverse" - frames = spinner["frames"].to_a.reverse.cycle - else - frames = spinner["frames"].cycle - end - elsif spinner["proc"] - frames = spinner["proc"].dup - else - raise(ArgumentError, "Whirly: Invalid spinner given") - end - - if frames.is_a? Proc - class << frames - alias next call - end - end - - frames - end - - # save options and preprocess, set defaults if value is still unknown - def self.configure(**options) - if !defined?(@configured) || !@configured || !defined?(@options) || !@options - @options = DEFAULT_OPTIONS.dup - @configured = true - end - - @options.merge!(options) - - spinner = configure_spinner(@options[:spinner]) - spinner_overwrites = {} - spinner_overwrites["mode"] = @options[:mode] if @options.key?(:mode) - @frames = configure_frames(spinner.merge(spinner_overwrites)) - - @interval = (@options[:interval] || spinner["interval"] || SOFT_DEFAULT_OPTIONS[:interval]) * 0.001 - @stop = @options[:stop] || spinner["stop"] - @status = @options[:status] - end - - def self.start(**options) - # optionally overwrite configuration on start - configure(**options) - - # only enable once - return false if defined?(@enabled) && @enabled - - # set status to enabled - @enabled = true - - # only do something if we are on a real terminal (or forced) - return false unless @options[:stream].tty? || @options[:non_tty] - - # ensure cursor is visible after exit the program (only register for the very first time) - if (!defined?(@at_exit_handler_registered) || !@at_exit_handler_registered) && @options[:hide_cursor] - @at_exit_handler_registered = true - stream = @options[:stream] - at_exit{ stream.print CLI_COMMANDS[:show_cursor] } - end - - # init color - initialize_color if @options[:color] - - # hide cursor - @options[:stream].print CLI_COMMANDS[:hide_cursor] if @options[:hide_cursor] - - # start spinner loop - @thread = Thread.new do - @current_frame = nil - while true # it's just a spinner, no exact timing here - next_color if @color - render - sleep(@interval) - end - end - - # idiomatic block syntax support - if block_given? - begin - yield - ensure - Whirly.stop - end - end - - true - end - - def self.stop(stop_frame = nil) - return false unless @enabled - @enabled = false - return false unless @options[:stream].tty? || @options[:non_tty] - - @thread.terminate if @thread - render(stop_frame || @stop) if stop_frame || @stop - unrender if @options[:remove_after_stop] - @options[:stream].puts if @options[:append_newline] - @options[:stream].print CLI_COMMANDS[:show_cursor] if @options[:hide_cursor] - - true - end - - def self.reset - at_exit_handler_registered = defined?(@at_exit_handler_registered) && @at_exit_handler_registered - instance_variables.each{ |iv| remove_instance_variable(iv) } - @at_exit_handler_registered = at_exit_handler_registered - @configured = false - end - - # - - - - - def self.unrender - return unless @current_frame - case @options[:ansi_escape_mode] - when "restore" - @options[:stream].print(render_prefix + ( - ' ' * (Unicode::DisplayWidth.of(@current_frame, @options[:ambiguous_character_width]) + 1) - ) + render_suffix) - when "line" - @options[:stream].print "\e[1K" - end - end - - def self.render(next_frame = nil) - unrender - - @current_frame = next_frame || @frames.next - @current_frame = Paint[@current_frame, @color] if @options[:color] - @current_frame += " #{@status}" if @status - - @options[:stream].print(render_prefix + @current_frame.to_s + render_suffix) - end - - def self.render_prefix - res = "" - res << "\n" if @options[:position] == "below" - res << "\e7" if @options[:ansi_escape_mode] == "restore" - res << "\e[G" if @options[:ansi_escape_mode] == "line" - res - end - - def self.render_suffix - res = "" - res << "\e8" if @options[:ansi_escape_mode] == "restore" - res << "\e[1A" if @options[:position] == "below" - res - end - - def self.initialize_color - if !defined?(Paint) - warn "Whirly warning: Using colors requires the paint gem" - else - @color = "%.6x" % rand(16777216) - @color_directions = (0..2).map{ |e| rand(3) - 1 } - end - end - - def self.next_color - @color = @color.scan(/../).map.with_index{ |c, i| - color_change = rand(@options[:color_change_rate]) * @color_directions[i] - nc = c.to_i(16) + color_change - if nc <= 0 - nc = 0 - @color_directions[i] = rand(3) - 1 - elsif nc >= 255 - nc = 255 - @color_directions[i] = rand(3) - 1 - end - "%.2x" % nc - }.join - end -end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners.rb deleted file mode 100644 index c72b037ae8655..0000000000000 --- a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Whirly - module Spinners - end -end - -require_relative "spinners/whirly" -require_relative "spinners/cli" diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/cli.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/cli.rb deleted file mode 100644 index 4fd2774730f6b..0000000000000 --- a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/cli.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "json" - -module Whirly - module Spinners - CLI = JSON.load(File.read(File.dirname(__FILE__) + "/../../../data/cli-spinners.json")).freeze - end -end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/whirly.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/whirly.rb deleted file mode 100644 index f40853b0cd17b..0000000000000 --- a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/spinners/whirly.rb +++ /dev/null @@ -1,15 +0,0 @@ -require "json" - -module Whirly - module Spinners - WHIRLY = { - "random_dots" => { "proc" => ->(){ [ 0x2800 + rand(256)].pack("U") }, "interval" => 100 }, - "mahjong" => { "proc" => ->(){ [0x1F000 + rand(44)].pack("U") }, "interval" => 200 }, - "domino" => { "proc" => ->(){ [0x1F030 + rand(50)].pack("U") }, "interval" => 200 }, - "vertical_domino" => { "proc" => ->(){ [0x1F062 + rand(50)].pack("U") }, "interval" => 200 } - } - WHIRLY.merge! JSON.load(File.read(File.dirname(__FILE__) + "/../../../data/whirly-static-spinners.json")) - - WHIRLY.freeze - end -end diff --git a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/version.rb b/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/version.rb deleted file mode 100644 index 4e33cef7c707b..0000000000000 --- a/Library/Homebrew/vendor/bundle/ruby/3.3.0/gems/whirly-0.3.0/lib/whirly/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -module Whirly - VERSION = "0.3.0" -end From 3b5b669b619f7b183cba20222f5a78ddeb584a94 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jul 2024 17:00:01 -0400 Subject: [PATCH 10/28] Improve output. --- Library/Homebrew/cmd/fetch.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index df9a9172576af..f3b3aac38e289 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -264,24 +264,23 @@ def run until remaining_downloads.empty? begin - finished_downloads = {} finished_states = [:fulfilled, :rejected] - remaining_downloads.each do |downloadable, promise| - break unless finished_states.include?(promise.state) - finished_downloads[downloadable] = remaining_downloads.delete(downloadable) - end + + finished_downloads, remaining_downloads = remaining_downloads.partition { |_,promise| finished_states.include?(promise.state) } finished_downloads.each do |downloadable, promise| previous_pending_line_count -= 1 + print "\033[K" output_message.call(downloadable, promise) end previous_pending_line_count = 0 remaining_downloads.each do |downloadable, promise| - break if previous_pending_line_count >= (Tty.height - 1) + break if previous_pending_line_count >= [concurrency, (Tty.height - 1)].min + print "\033[K" previous_pending_line_count += output_message.call(downloadable, promise) end @@ -289,6 +288,8 @@ def run $stdout.print "\033[#{previous_pending_line_count}A" $stdout.flush end + + sleep 0.05 rescue Interrupt print "\n" * previous_pending_line_count raise From a114575663b6580408551f8fbda3712effcf6b4e Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jul 2024 20:46:15 -0400 Subject: [PATCH 11/28] Fix wrong terminal size. --- Library/Homebrew/utils/tty.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/utils/tty.rb b/Library/Homebrew/utils/tty.rb index c10720aa4e1f1..3e7c9d86bc180 100644 --- a/Library/Homebrew/utils/tty.rb +++ b/Library/Homebrew/utils/tty.rb @@ -63,7 +63,7 @@ def show_cursor sig { returns(T.nilable([Integer, Integer])) } def size - `/bin/stty size 2>/dev/null`.split&.map(&:to_i) + `/bin/stty size 2>/dev/null`.presence&.split&.map(&:to_i) end sig { returns(Integer) } From 786f5d359fe2b19c9ce5df2478c7d9222ff15463 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jul 2024 21:02:09 -0400 Subject: [PATCH 12/28] Remove unneeded method. --- Library/Homebrew/api/download.rb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Library/Homebrew/api/download.rb b/Library/Homebrew/api/download.rb index 947605805a9a9..e848daf328481 100644 --- a/Library/Homebrew/api/download.rb +++ b/Library/Homebrew/api/download.rb @@ -6,11 +6,6 @@ module Homebrew module API class DownloadStrategy < CurlDownloadStrategy - sig { returns(String) } - def name # rubocop:disable Lint/UselessMethodDefinition - super - end - sig { override.returns(Pathname) } def symlink_location cache/name @@ -43,12 +38,12 @@ def downloader sig { override.returns(String) } def name - downloader.name + download_name end sig { override.returns(String) } def download_type - "API" + "API source" end sig { override.returns(Pathname) } From 0cafa83f8a07cb8c9d98e2bbdcb6c8caea0d11a3 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jul 2024 21:09:26 -0400 Subject: [PATCH 13/28] Simplify `Tty` methods. --- Library/Homebrew/utils/tty.rb | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/Library/Homebrew/utils/tty.rb b/Library/Homebrew/utils/tty.rb index 3e7c9d86bc180..cf500c0fb389b 100644 --- a/Library/Homebrew/utils/tty.rb +++ b/Library/Homebrew/utils/tty.rb @@ -63,27 +63,22 @@ def show_cursor sig { returns(T.nilable([Integer, Integer])) } def size - `/bin/stty size 2>/dev/null`.presence&.split&.map(&:to_i) + return @size if defined?(@size) + + height, width = `/bin/stty size 2>/dev/null`.presence&.split&.map(&:to_i) + return if height.nil? || width.nil? + + @size = [height, width] end sig { returns(Integer) } def height - @height ||= begin - height, = size - height, = `/usr/bin/tput lines 2>/dev/null`.split if height.zero? - height ||= 40 - height.to_i - end + @height ||= size&.first || `/usr/bin/tput lines 2>/dev/null`.presence&.to_i || 40 end sig { returns(Integer) } def width - @width ||= begin - _, width = size - width, = `/usr/bin/tput cols 2>/dev/null`.split if width.zero? - width ||= 80 - width.to_i - end + @width ||= size&.second || `/usr/bin/tput cols 2>/dev/null`.presence&.to_i || 80 end sig { params(string: String).returns(String) } From 0b50f0651ee7a3b8b26f35f1db3070367b3b017b Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Mon, 15 Jul 2024 21:17:45 -0400 Subject: [PATCH 14/28] Fix code style. --- Library/Homebrew/cmd/fetch.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index f3b3aac38e289..d35680936bf15 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -264,11 +264,11 @@ def run until remaining_downloads.empty? begin - finished_states = [:fulfilled, :rejected] - - finished_downloads, remaining_downloads = remaining_downloads.partition { |_,promise| finished_states.include?(promise.state) } + finished_downloads, remaining_downloads = remaining_downloads.partition do |_, promise| + finished_states.include?(promise.state) + end finished_downloads.each do |downloadable, promise| previous_pending_line_count -= 1 From d6ebb04ff5b51633c9e4e3dc71a37dd06eb28650 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 16 Jul 2024 00:01:40 -0400 Subject: [PATCH 15/28] Improve output. --- Library/Homebrew/cmd/fetch.rb | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index d35680936bf15..069abe2230ac2 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -82,12 +82,16 @@ def download_queue class Spinner FRAMES = [ - "◜", - "◠", - "◝", - "◞", - "◡", - "◟", + "⠋", + "⠙", + "⠚", + "⠞", + "⠖", + "⠦", + "⠴", + "⠲", + "⠳", + "⠓", ].freeze sig { void } @@ -221,22 +225,20 @@ def run end if concurrency == 1 - downloads.each_value do |promise| + downloads.each do |downloadable, promise| promise.wait! rescue ChecksumMismatchError => e opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" Homebrew.failed = true if downloadable.is_a?(Resource::Patch) end else - spinner = Spinner.new - remaining_downloads = downloads.dup - previous_pending_line_count = 0 begin - print Tty.hide_cursor + $stdout.print Tty.hide_cursor + $stdout.flush output_message = lambda do |downloadable, promise| status = case promise.state @@ -245,13 +247,14 @@ def run when :rejected "#{Tty.red}✘#{Tty.reset}" when :pending - spinner + "#{Tty.blue}#{spinner}#{Tty.reset}" else raise promise.state end message = "#{downloadable.download_type.capitalize} #{downloadable.name}" - puts "#{status} #{message}" + $stdout.puts "#{status} #{message}" + $stdout.flush if promise.rejected? && (e = promise.reason).is_a?(ChecksumMismatchError) opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" @@ -273,6 +276,7 @@ def run finished_downloads.each do |downloadable, promise| previous_pending_line_count -= 1 print "\033[K" + $stdout.flush output_message.call(downloadable, promise) end @@ -281,6 +285,7 @@ def run break if previous_pending_line_count >= [concurrency, (Tty.height - 1)].min print "\033[K" + $stdout.flush previous_pending_line_count += output_message.call(downloadable, promise) end @@ -292,11 +297,13 @@ def run sleep 0.05 rescue Interrupt print "\n" * previous_pending_line_count + $stdout.flush raise end end ensure - print Tty.show_cursor + $stdout.print Tty.show_cursor + $stdout.flush end end From e7c9049a3c6630b18eceaa961d30a9da09d0877c Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 16 Jul 2024 10:18:26 -0400 Subject: [PATCH 16/28] Use futures instead of promises. --- Library/Homebrew/cmd/fetch.rb | 26 ++++++++++++-------------- Library/Homebrew/download_queue.rb | 15 ++++++++++----- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 069abe2230ac2..0b0018e8a6b07 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -240,23 +240,23 @@ def run $stdout.print Tty.hide_cursor $stdout.flush - output_message = lambda do |downloadable, promise| - status = case promise.state + output_message = lambda do |downloadable, future| + status = case future.state when :fulfilled "#{Tty.green}✔︎#{Tty.reset}" when :rejected "#{Tty.red}✘#{Tty.reset}" - when :pending + when :pending, :processing "#{Tty.blue}#{spinner}#{Tty.reset}" else - raise promise.state + raise future.state.to_s end message = "#{downloadable.download_type.capitalize} #{downloadable.name}" $stdout.puts "#{status} #{message}" $stdout.flush - if promise.rejected? && (e = promise.reason).is_a?(ChecksumMismatchError) + if future.rejected? && (e = future.reason).is_a?(ChecksumMismatchError) opoo "#{downloadable.download_type.capitalize} reports different checksum: #{e.expected}" Homebrew.failed = true if downloadable.is_a?(Resource::Patch) next 2 @@ -269,24 +269,24 @@ def run begin finished_states = [:fulfilled, :rejected] - finished_downloads, remaining_downloads = remaining_downloads.partition do |_, promise| - finished_states.include?(promise.state) + finished_downloads, remaining_downloads = remaining_downloads.partition do |_, future| + finished_states.include?(future.state) end - finished_downloads.each do |downloadable, promise| + finished_downloads.each do |downloadable, future| previous_pending_line_count -= 1 print "\033[K" $stdout.flush - output_message.call(downloadable, promise) + output_message.call(downloadable, future) end previous_pending_line_count = 0 - remaining_downloads.each do |downloadable, promise| + remaining_downloads.each do |downloadable, future| break if previous_pending_line_count >= [concurrency, (Tty.height - 1)].min print "\033[K" $stdout.flush - previous_pending_line_count += output_message.call(downloadable, promise) + previous_pending_line_count += output_message.call(downloadable, future) end if previous_pending_line_count.positive? @@ -317,9 +317,7 @@ def downloads end def fetch_downloadable(downloadable) - downloadable.clear_cache if args.force? - - downloads[downloadable] ||= download_queue.enqueue(RetryableDownload.new(downloadable)) + downloads[downloadable] ||= download_queue.enqueue(RetryableDownload.new(downloadable), force: args.force?) end end end diff --git a/Library/Homebrew/download_queue.rb b/Library/Homebrew/download_queue.rb index 29d97d39d05a6..7fac89fa20495 100644 --- a/Library/Homebrew/download_queue.rb +++ b/Library/Homebrew/download_queue.rb @@ -2,7 +2,7 @@ # frozen_string_literal: true require "downloadable" -require "concurrent/promise" +require "concurrent/promises" require "concurrent/executors" module Homebrew @@ -16,11 +16,16 @@ def initialize(size = 1) @pool = Concurrent::FixedThreadPool.new(size) end - sig { params(downloadable: Downloadable).returns(Concurrent::Promise) } - def enqueue(downloadable) - Concurrent::Promise.execute(executor: pool) do - downloadable.fetch(quiet: pool.max_length > 1) + sig { params(downloadable: Downloadable, force: T::Boolean).returns(Concurrent::Promises::Future) } + def enqueue(downloadable, force: false) + quiet = pool.max_length > 1 + # Passing in arguments from outside into the future is a common `concurrent-ruby` pattern. + # rubocop:disable Lint/ShadowingOuterLocalVariable + Concurrent::Promises.future_on(pool, downloadable, force, quiet) do |downloadable, force, quiet| + downloadable.clear_cache if force + downloadable.fetch(quiet:) end + # rubocop:enable Lint/ShadowingOuterLocalVariable end sig { void } From 404176af1d6be52047c7dbe7271fae9fb3919c0e Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 14 Aug 2024 21:59:04 +0200 Subject: [PATCH 17/28] Implement `Downloadable` for more types. --- Library/Homebrew/cmd/fetch.rb | 4 ++++ Library/Homebrew/cmd/install.rb | 1 - Library/Homebrew/download_strategy.rb | 8 -------- Library/Homebrew/downloadable.rb | 2 +- Library/Homebrew/formula.rb | 2 ++ Library/Homebrew/formula_installer.rb | 4 ++-- Library/Homebrew/resource.rb | 27 +++++++++++++++++++++++++++ 7 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 0b0018e8a6b07..359b3c5d2ba2b 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -296,6 +296,10 @@ def run sleep 0.05 rescue Interrupt + remaining_downloads.each do |_, future| + # FIXME: Implement cancellation of running downloads. + end + print "\n" * previous_pending_line_count $stdout.flush raise diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 8a7c0fc80d6ed..fe9ac9869e7ad 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -207,7 +207,6 @@ def run end if casks.any? - if args.dry_run? if (casks_to_install = casks.reject(&:installed?).presence) ohai "Would install #{::Utils.pluralize("cask", casks_to_install.count, include_count: true)}:" diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 39b81a10739a2..2ee605c9a4cf2 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -710,14 +710,6 @@ def stage end end -# Strategy for extracting local binary packages. -class LocalBottleDownloadStrategy < AbstractFileDownloadStrategy - def initialize(path) # rubocop:disable Lint/MissingSuper - @cached_location = path - extend Pourable - end -end - # Strategy for downloading a Subversion repository. # # @api public diff --git a/Library/Homebrew/downloadable.rb b/Library/Homebrew/downloadable.rb index 9afb25d55a313..a39d5d7b48e8c 100644 --- a/Library/Homebrew/downloadable.rb +++ b/Library/Homebrew/downloadable.rb @@ -126,7 +126,7 @@ def verify_download_integrity(filename) sig { overridable.returns(String) } def download_name - File.basename(determine_url.to_s) + @download_name ||= File.basename(determine_url.to_s) end private diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 62c88710f13c1..3bff94377d0ce 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -2773,10 +2773,12 @@ def on_system_blocks_exist? ).returns(Pathname) } def fetch(verify_download_integrity: true, timeout: nil, quiet: false) + odeprecated "Formula#fetch", "Resource#fetch on Formula#resource" active_spec.fetch(verify_download_integrity:, timeout:, quiet:) end def verify_download_integrity(filename) + odeprecated "Formula#verify_download_integrity", "Resource#verify_download_integrity on Formula#resource" active_spec.verify_download_integrity(filename) end diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index eeaaf127d74f8..8a44bae259ae5 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -1261,11 +1261,11 @@ def fetch def downloader if (bottle_path = formula.local_bottle_path) - LocalBottleDownloadStrategy.new(bottle_path) + Resource::Local.new(bottle_path) elsif pour_bottle? formula.bottle else - formula + formula.resource end end diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index 8471fbca44f53..cd0a64133b19f 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -269,6 +269,33 @@ def determine_url_mirrors [*extra_urls, *super].uniq end + # A local resource that doesn't need to be downloaded. + class Local < Resource + def initialize(path) + super(File.basename(path)) + @path = path + end + + sig { override.returns(Pathname) } + def cached_download + @path + end + + sig { override.void } + def clear_cache; end + + sig { + override.params( + verify_download_integrity: T::Boolean, + timeout: T.nilable(T.any(Integer, Float)), + quiet: T::Boolean, + ).returns(Pathname) + } + def fetch(verify_download_integrity: true, timeout: nil, quiet: false) + cached_download + end + end + # A resource for a formula. class Formula < Resource sig { override.returns(String) } From 984cde114a204396c5dea3a44ce02f5a74e65611 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 14 Aug 2024 21:41:01 +0200 Subject: [PATCH 18/28] Move escape codes to `Tty`. --- Library/Homebrew/cmd/fetch.rb | 13 ++++++++----- Library/Homebrew/utils/tty.rb | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 359b3c5d2ba2b..484f9647425c9 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -275,7 +275,7 @@ def run finished_downloads.each do |downloadable, future| previous_pending_line_count -= 1 - print "\033[K" + $stdout.print Tty.clear_to_end $stdout.flush output_message.call(downloadable, future) end @@ -284,13 +284,13 @@ def run remaining_downloads.each do |downloadable, future| break if previous_pending_line_count >= [concurrency, (Tty.height - 1)].min - print "\033[K" + $stdout.print Tty.clear_to_end $stdout.flush previous_pending_line_count += output_message.call(downloadable, future) end if previous_pending_line_count.positive? - $stdout.print "\033[#{previous_pending_line_count}A" + $stdout.print Tty.move_cursor_up(previous_pending_line_count) $stdout.flush end @@ -300,8 +300,11 @@ def run # FIXME: Implement cancellation of running downloads. end - print "\n" * previous_pending_line_count - $stdout.flush + if previous_pending_line_count.positive? + $stdout.print Tty.move_cursor_down(previous_pending_line_count - 1) + $stdout.flush + end + raise end end diff --git a/Library/Homebrew/utils/tty.rb b/Library/Homebrew/utils/tty.rb index cf500c0fb389b..9071c00ef6b63 100644 --- a/Library/Homebrew/utils/tty.rb +++ b/Library/Homebrew/utils/tty.rb @@ -51,6 +51,21 @@ def strip_ansi(string) string.gsub(/\033\[\d+(;\d+)*m/, "") end + sig { params(line_count: Integer).returns(String) } + def move_cursor_up(line_count) + "\033[#{line_count}A" + end + + sig { params(line_count: Integer).returns(String) } + def move_cursor_down(line_count) + "\033[#{line_count}B" + end + + sig { returns(String) } + def clear_to_end + "\033[K" + end + sig { returns(String) } def hide_cursor "\033[?25l" From 9fd4c97facec55e6cbf25ffca15ec7c6dd65d644 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 21 Aug 2024 23:01:48 +0200 Subject: [PATCH 19/28] Add method for moving cursor up and to the beginning. --- Library/Homebrew/cmd/fetch.rb | 2 +- Library/Homebrew/utils/tty.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 484f9647425c9..9b896ada143cd 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -290,7 +290,7 @@ def run end if previous_pending_line_count.positive? - $stdout.print Tty.move_cursor_up(previous_pending_line_count) + $stdout.print Tty.move_cursor_up_beginning(previous_pending_line_count) $stdout.flush end diff --git a/Library/Homebrew/utils/tty.rb b/Library/Homebrew/utils/tty.rb index 9071c00ef6b63..a539e37b5b13b 100644 --- a/Library/Homebrew/utils/tty.rb +++ b/Library/Homebrew/utils/tty.rb @@ -56,6 +56,11 @@ def move_cursor_up(line_count) "\033[#{line_count}A" end + sig { params(line_count: Integer).returns(String) } + def move_cursor_up_beginning(line_count) + "\033[#{line_count}F" + end + sig { params(line_count: Integer).returns(String) } def move_cursor_down(line_count) "\033[#{line_count}B" From 231ac720d2750fb8b7b47fccbe60596c2f95f5ec Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 4 Sep 2024 22:40:21 +0200 Subject: [PATCH 20/28] Add FIXME comment. --- Library/Homebrew/cmd/fetch.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 9b896ada143cd..d1309bdec732d 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -282,6 +282,7 @@ def run previous_pending_line_count = 0 remaining_downloads.each do |downloadable, future| + # FIXME: Allow printing full terminal height. break if previous_pending_line_count >= [concurrency, (Tty.height - 1)].min $stdout.print Tty.clear_to_end From fb0bf3b7a228e7b7d74ed5066c37974de015bc4c Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 4 Sep 2024 23:12:58 +0200 Subject: [PATCH 21/28] Fix wrong `stage` method being called. --- Library/Homebrew/download_strategy.rb | 11 +++++++++++ Library/Homebrew/formula_installer.rb | 6 +++--- Library/Homebrew/resource.rb | 21 +-------------------- Library/Homebrew/software_spec.rb | 6 ++---- 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index 2ee605c9a4cf2..d16552fe02954 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -710,6 +710,17 @@ def stage end end +# Strategy for extracting local binary packages. +class LocalBottleDownloadStrategy < AbstractFileDownloadStrategy + def initialize(path) # rubocop:disable Lint/MissingSuper + @cached_location = path + end + + def clear_cache + # Path is used directly and not cached. + end +end + # Strategy for downloading a Subversion repository. # # @api public diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index 8a44bae259ae5..50e15f4715ae8 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -1254,12 +1254,12 @@ def fetch formula.fetch_patches formula.resources.each(&:fetch) end - downloader.fetch + downloadable.downloader.fetch self.class.fetched << formula end - def downloader + def downloadable if (bottle_path = formula.local_bottle_path) Resource::Local.new(bottle_path) elsif pour_bottle? @@ -1324,7 +1324,7 @@ def pour end HOMEBREW_CELLAR.cd do - downloader.stage + downloadable.downloader.stage end Tab.clear_cache diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb index cd0a64133b19f..d663ec3bab4b3 100644 --- a/Library/Homebrew/resource.rb +++ b/Library/Homebrew/resource.rb @@ -273,26 +273,7 @@ def determine_url_mirrors class Local < Resource def initialize(path) super(File.basename(path)) - @path = path - end - - sig { override.returns(Pathname) } - def cached_download - @path - end - - sig { override.void } - def clear_cache; end - - sig { - override.params( - verify_download_integrity: T::Boolean, - timeout: T.nilable(T.any(Integer, Float)), - quiet: T::Boolean, - ).returns(Pathname) - } - def fetch(verify_download_integrity: true, timeout: nil, quiet: false) - cached_download + @downloader = LocalBottleDownloadStrategy.new(path) end end diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb index 81a9b192ee28c..2fd01ea0e4cfa 100644 --- a/Library/Homebrew/software_spec.rb +++ b/Library/Homebrew/software_spec.rb @@ -352,7 +352,7 @@ def extname attr_reader :name, :resource, :tag, :cellar, :rebuild def_delegators :resource, :url, :verify_download_integrity - def_delegators :resource, :cached_download + def_delegators :resource, :cached_download, :downloader def initialize(formula, spec, tag = nil) super() @@ -408,9 +408,7 @@ def skip_relocation? @spec.skip_relocation?(tag: @tag) end - def stage - resource.downloader.stage - end + def stage = downloader.stage def fetch_tab(timeout: nil, quiet: false) return unless (resource = github_packages_manifest_resource) From c61713b8e02336e7e9c1533865327dcee0dc6412 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 5 Sep 2024 17:14:40 +0200 Subject: [PATCH 22/28] Fix handling for `--retry` flag. --- Library/Homebrew/cmd/fetch.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index d1309bdec732d..47d0b44d01b3b 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -325,7 +325,8 @@ def downloads end def fetch_downloadable(downloadable) - downloads[downloadable] ||= download_queue.enqueue(RetryableDownload.new(downloadable), force: args.force?) + tries = args.retry? ? {} : { tries: 1 } + downloads[downloadable] ||= download_queue.enqueue(RetryableDownload.new(downloadable, **tries), force: args.force?) end end end From 123a2ac84c022cbc06f4ca3a77c3439cd05e1dca Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 5 Sep 2024 17:18:00 +0200 Subject: [PATCH 23/28] Comment deprecations. Co-authored-by: Bo Anderson --- Library/Homebrew/formula.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 3bff94377d0ce..79ae91ea1d61e 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -2773,12 +2773,12 @@ def on_system_blocks_exist? ).returns(Pathname) } def fetch(verify_download_integrity: true, timeout: nil, quiet: false) - odeprecated "Formula#fetch", "Resource#fetch on Formula#resource" + # odeprecated "Formula#fetch", "Resource#fetch on Formula#resource" active_spec.fetch(verify_download_integrity:, timeout:, quiet:) end def verify_download_integrity(filename) - odeprecated "Formula#verify_download_integrity", "Resource#verify_download_integrity on Formula#resource" + # odeprecated "Formula#verify_download_integrity", "Resource#verify_download_integrity on Formula#resource" active_spec.verify_download_integrity(filename) end From 846cf25043ab54fa00ef4ab00fd49ceb33ea0311 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 5 Sep 2024 17:19:07 +0200 Subject: [PATCH 24/28] Fix wrong argument passing. --- Library/Homebrew/formula.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 79ae91ea1d61e..4ea75967020f2 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -567,7 +567,13 @@ def synced_with_other_formulae? params(name: String, klass: T.class_of(Resource), block: T.nilable(T.proc.bind(Resource).void)) .returns(T.nilable(Resource)) } - def resource(name = T.unsafe(nil), klass = T.unsafe(nil), &block) = active_spec.resource(*name, *klass, &block) + def resource(name = T.unsafe(nil), klass = T.unsafe(nil), &block) + if klass.nil? + active_spec.resource(*name, &block) + else + active_spec.resource(name, klass) + end + end # Old names for the formula. # From a97006565743378ffe3411f8ee34492eb190d6c9 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 5 Sep 2024 17:20:20 +0200 Subject: [PATCH 25/28] Fix wrong argument passing. --- Library/Homebrew/formula.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 4ea75967020f2..b0cd72fcfb902 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -571,7 +571,7 @@ def resource(name = T.unsafe(nil), klass = T.unsafe(nil), &block) if klass.nil? active_spec.resource(*name, &block) else - active_spec.resource(name, klass) + active_spec.resource(name, klass, &block) end end From 60cb8101f535ffd01b4232ba41f30bf11493cfd3 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 5 Sep 2024 17:21:41 +0200 Subject: [PATCH 26/28] Readd `Pourable` to `LocalBottleDownloadStrategy`. --- Library/Homebrew/download_strategy.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/Library/Homebrew/download_strategy.rb b/Library/Homebrew/download_strategy.rb index d16552fe02954..9a895611b8d3c 100644 --- a/Library/Homebrew/download_strategy.rb +++ b/Library/Homebrew/download_strategy.rb @@ -714,6 +714,7 @@ def stage class LocalBottleDownloadStrategy < AbstractFileDownloadStrategy def initialize(path) # rubocop:disable Lint/MissingSuper @cached_location = path + extend Pourable end def clear_cache From 69a04bd2491d36d9516fd0fab4832c7e80c579de Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 5 Sep 2024 18:11:49 +0200 Subject: [PATCH 27/28] Fix code style. --- Library/Homebrew/cmd/fetch.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 47d0b44d01b3b..670a4250930cd 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -325,8 +325,10 @@ def downloads end def fetch_downloadable(downloadable) - tries = args.retry? ? {} : { tries: 1 } - downloads[downloadable] ||= download_queue.enqueue(RetryableDownload.new(downloadable, **tries), force: args.force?) + downloads[downloadable] ||= begin + tries = args.retry? ? {} : { tries: 1 } + download_queue.enqueue(RetryableDownload.new(downloadable, **tries), force: args.force?) + end end end end From b68ee4142ff179d4b468902054ac907642448f97 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Sat, 7 Sep 2024 14:45:30 +0200 Subject: [PATCH 28/28] Ensure thread-pool shutdown. --- Library/Homebrew/cmd/fetch.rb | 4 +++- Library/Homebrew/download_queue.rb | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Library/Homebrew/cmd/fetch.rb b/Library/Homebrew/cmd/fetch.rb index 670a4250930cd..6bd826c48d25e 100644 --- a/Library/Homebrew/cmd/fetch.rb +++ b/Library/Homebrew/cmd/fetch.rb @@ -301,6 +301,8 @@ def run # FIXME: Implement cancellation of running downloads. end + download_queue.cancel + if previous_pending_line_count.positive? $stdout.print Tty.move_cursor_down(previous_pending_line_count - 1) $stdout.flush @@ -314,7 +316,7 @@ def run $stdout.flush end end - + ensure download_queue.shutdown end diff --git a/Library/Homebrew/download_queue.rb b/Library/Homebrew/download_queue.rb index 7fac89fa20495..e591c3f2ae5e5 100644 --- a/Library/Homebrew/download_queue.rb +++ b/Library/Homebrew/download_queue.rb @@ -28,9 +28,18 @@ def enqueue(downloadable, force: false) # rubocop:enable Lint/ShadowingOuterLocalVariable end + sig { void } + def cancel + # FIXME: Implement graceful cancellaction of running downloads based on + # https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Cancellation.html + # instead of killing the whole thread pool. + pool.kill + end + sig { void } def shutdown pool.shutdown + pool.wait_for_termination end end end