farce 0.0.1.alpha2-x86_64-linux-gnu
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +26 -0
- data/CONTRIBUTING.md +71 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1524 -0
- data/SECURITY.md +10 -0
- data/docs/benchmarks.md +185 -0
- data/docs/gems/dry-types.md +290 -0
- data/docs/gems/msgpack.md +70 -0
- data/docs/gems/ractor-shim.md +63 -0
- data/docs/modes.md +628 -0
- data/docs/scopes.md +649 -0
- data/docs/variants.md +346 -0
- data/ext/ext_helper.rb +20 -0
- data/ext/farce/README.md +21 -0
- data/ext/farce/atom.c +1023 -0
- data/ext/farce/bounded_map.c +1683 -0
- data/ext/farce/containers.h +77 -0
- data/ext/farce/counter.c +399 -0
- data/ext/farce/darwin.c +100 -0
- data/ext/farce/depend +12 -0
- data/ext/farce/dict.c +1523 -0
- data/ext/farce/dict.h +152 -0
- data/ext/farce/drivers.c +237 -0
- data/ext/farce/exchanger.c +299 -0
- data/ext/farce/extconf.rb +99 -0
- data/ext/farce/farce.c +359 -0
- data/ext/farce/flag.c +288 -0
- data/ext/farce/io.c +338 -0
- data/ext/farce/lock.c +510 -0
- data/ext/farce/map.c +2240 -0
- data/ext/farce/priority_queue.c +2056 -0
- data/ext/farce/queue.c +1059 -0
- data/ext/farce/reactor.c +820 -0
- data/ext/farce/reactor.h +103 -0
- data/ext/farce/shareable.h +31 -0
- data/ext/farce/signal.c +350 -0
- data/ext/farce/transaction.c +354 -0
- data/ext/farce/transaction.h +40 -0
- data/ext/farce/tree_map.c +1953 -0
- data/ext/farce/trie.c +2020 -0
- data/ext/farce/unshareable.c +155 -0
- data/ext/farce/unshared_io_pool.h +234 -0
- data/ext/farce/unshared_signal.c +263 -0
- data/ext/farce/unshared_wait.h +193 -0
- data/ext/farce/unsupported.c +6 -0
- data/ext/farce/vector.c +1195 -0
- data/ext/farce/weak_map.c +1714 -0
- data/ext/java/org/farce/BoundedMap.java +394 -0
- data/ext/java/org/farce/FiberScheduler.java +141 -0
- data/ext/java/org/farce/PriorityKey.java +45 -0
- data/ext/java/org/farce/PriorityQueue.java +373 -0
- data/ext/java/org/farce/QueueSignal.java +28 -0
- data/ext/rebind/README.md +14 -0
- data/ext/rebind/extconf.rb +10 -0
- data/ext/rebind/rebind.c +186 -0
- data/lib/farce/_yard/internal.rb +13 -0
- data/lib/farce/_yard/macros.rb +61 -0
- data/lib/farce/_yard/ractor.rb +46 -0
- data/lib/farce/abstract/atom.rb +186 -0
- data/lib/farce/abstract/bounded_map.rb +232 -0
- data/lib/farce/abstract/collection.rb +151 -0
- data/lib/farce/abstract/concurrent_map.rb +381 -0
- data/lib/farce/abstract/counter.rb +193 -0
- data/lib/farce/abstract/duplicable_map.rb +229 -0
- data/lib/farce/abstract/exchanger.rb +26 -0
- data/lib/farce/abstract/flag.rb +71 -0
- data/lib/farce/abstract/lazy.rb +115 -0
- data/lib/farce/abstract/lease.rb +104 -0
- data/lib/farce/abstract/lease_map.rb +261 -0
- data/lib/farce/abstract/lease_pool.rb +91 -0
- data/lib/farce/abstract/lfu_map.rb +20 -0
- data/lib/farce/abstract/lru_map.rb +25 -0
- data/lib/farce/abstract/map.rb +345 -0
- data/lib/farce/abstract/molecule.rb +245 -0
- data/lib/farce/abstract/port.rb +74 -0
- data/lib/farce/abstract/priority_queue.rb +117 -0
- data/lib/farce/abstract/queue.rb +269 -0
- data/lib/farce/abstract/scheduler.rb +111 -0
- data/lib/farce/abstract/set.rb +910 -0
- data/lib/farce/abstract/sorted_set.rb +172 -0
- data/lib/farce/abstract/timer_queue.rb +136 -0
- data/lib/farce/abstract/tree_map.rb +269 -0
- data/lib/farce/abstract/value.rb +68 -0
- data/lib/farce/abstract/vector.rb +1126 -0
- data/lib/farce/abstract/weak_atom.rb +32 -0
- data/lib/farce/abstract/weak_key_map.rb +12 -0
- data/lib/farce/abstract/weak_map.rb +13 -0
- data/lib/farce/abstract/weak_set.rb +12 -0
- data/lib/farce/abstract/weak_value_map.rb +12 -0
- data/lib/farce/abstract.rb +17 -0
- data/lib/farce/atom.rb +293 -0
- data/lib/farce/class_mirror.rb +87 -0
- data/lib/farce/clock.rb +121 -0
- data/lib/farce/config.rb +229 -0
- data/lib/farce/counter.rb +71 -0
- data/lib/farce/deduper.rb +122 -0
- data/lib/farce/engine/jruby/bounded_map.rb +314 -0
- data/lib/farce/engine/jruby/fiber_scheduler.jar +0 -0
- data/lib/farce/engine/jruby/fiber_scheduler.rb +119 -0
- data/lib/farce/engine/jruby/lease_waiting.rb +19 -0
- data/lib/farce/engine/jruby/map.rb +505 -0
- data/lib/farce/engine/jruby/mutable_numeric_copy.rb +42 -0
- data/lib/farce/engine/jruby/signal.rb +147 -0
- data/lib/farce/engine/jruby.rb +63 -0
- data/lib/farce/engine/jvm/concurrent_weak_registry.rb +55 -0
- data/lib/farce/engine/jvm/counter.rb +102 -0
- data/lib/farce/engine/jvm/extension.rb +32 -0
- data/lib/farce/engine/jvm/farce.jar +0 -0
- data/lib/farce/engine/jvm/flag.rb +79 -0
- data/lib/farce/engine/jvm/priority_queue.rb +217 -0
- data/lib/farce/engine/jvm/tree_map.rb +350 -0
- data/lib/farce/engine/jvm/types.rb +180 -0
- data/lib/farce/engine/jvm.rb +19 -0
- data/lib/farce/engine/ruby/3.4/farce.so +0 -0
- data/lib/farce/engine/ruby/3.4/fiber_scheduler.rb +20 -0
- data/lib/farce/engine/ruby/3.4/port.rb +186 -0
- data/lib/farce/engine/ruby/3.4/ractor_methods.rb +26 -0
- data/lib/farce/engine/ruby/3.4/ractor_selector.rb +92 -0
- data/lib/farce/engine/ruby/3.4/rebind.so +0 -0
- data/lib/farce/engine/ruby/3.4/vault.rb +56 -0
- data/lib/farce/engine/ruby/4.0/farce.so +0 -0
- data/lib/farce/engine/ruby/4.0/port.rb +19 -0
- data/lib/farce/engine/ruby/4.0/ractor_methods.rb +20 -0
- data/lib/farce/engine/ruby/4.0/ractor_selector.rb +108 -0
- data/lib/farce/engine/ruby/4.0/rebind.so +0 -0
- data/lib/farce/engine/ruby/4.0/vault.rb +74 -0
- data/lib/farce/engine/ruby/4.1/port.rb +21 -0
- data/lib/farce/engine/ruby/4.1/ractor_methods.rb +22 -0
- data/lib/farce/engine/ruby/4.1/ractor_selector.rb +25 -0
- data/lib/farce/engine/ruby/4.1/vault.rb +5 -0
- data/lib/farce/engine/ruby/fiber_scheduler.rb +32 -0
- data/lib/farce/engine/ruby/key_lock_map.rb +28 -0
- data/lib/farce/engine/ruby/shared/lease.rb +26 -0
- data/lib/farce/engine/ruby/shared/lease_pool.rb +24 -0
- data/lib/farce/engine/ruby/shared/main_scheduler.rb +9 -0
- data/lib/farce/engine/ruby/shared/parallel_scheduler.rb +9 -0
- data/lib/farce/engine/ruby/shared/proxy_owner.rb +31 -0
- data/lib/farce/engine/ruby/shared/ractor_methods.rb +34 -0
- data/lib/farce/engine/ruby/shared/ractor_selector.rb +328 -0
- data/lib/farce/engine/ruby/shared/strict_map.rb +13 -0
- data/lib/farce/engine/ruby/shared/unshared_vector.rb +14 -0
- data/lib/farce/engine/ruby/shared/vault.rb +144 -0
- data/lib/farce/engine/ruby/shared/vault_weak_map.rb +336 -0
- data/lib/farce/engine/ruby/shared/weak_atom.rb +54 -0
- data/lib/farce/engine/ruby/shared/weak_map.rb +413 -0
- data/lib/farce/engine/ruby.rb +130 -0
- data/lib/farce/engine/shared/atom.rb +10 -0
- data/lib/farce/engine/shared/exchanger.rb +130 -0
- data/lib/farce/engine/shared/identity_key.rb +22 -0
- data/lib/farce/engine/shared/lease.rb +10 -0
- data/lib/farce/engine/shared/lease_pool.rb +10 -0
- data/lib/farce/engine/shared/main_scheduler.rb +20 -0
- data/lib/farce/engine/shared/map_key_coordination.rb +226 -0
- data/lib/farce/engine/shared/parallel_scheduler.rb +9 -0
- data/lib/farce/engine/shared/port.rb +44 -0
- data/lib/farce/engine/shared/portable_bounded_map.rb +619 -0
- data/lib/farce/engine/shared/proxy_owner.rb +43 -0
- data/lib/farce/engine/shared/queue.rb +233 -0
- data/lib/farce/engine/shared/ractor_methods.rb +73 -0
- data/lib/farce/engine/shared/rebindable.rb +15 -0
- data/lib/farce/engine/shared/strict_atom.rb +73 -0
- data/lib/farce/engine/shared/strict_map.rb +117 -0
- data/lib/farce/engine/shared/strict_queue_values.rb +27 -0
- data/lib/farce/engine/shared/strict_tree_map.rb +56 -0
- data/lib/farce/engine/shared/transaction_map_backend.rb +20 -0
- data/lib/farce/engine/shared/trie.rb +317 -0
- data/lib/farce/engine/shared/trie_builder.rb +199 -0
- data/lib/farce/engine/shared/unshareable.rb +14 -0
- data/lib/farce/engine/shared/unshared_atom.rb +256 -0
- data/lib/farce/engine/shared/unshared_priority_queue.rb +9 -0
- data/lib/farce/engine/shared/unshared_queue.rb +18 -0
- data/lib/farce/engine/shared/unshared_signal.rb +21 -0
- data/lib/farce/engine/shared/unshared_vector.rb +377 -0
- data/lib/farce/engine/shared/unshared_weak_atom.rb +30 -0
- data/lib/farce/engine/shared/unshared_weak_map.rb +445 -0
- data/lib/farce/engine/shared/vault.rb +31 -0
- data/lib/farce/engine/shared/vector.rb +83 -0
- data/lib/farce/engine/shared/weak_atom/base.rb +189 -0
- data/lib/farce/engine/shared/weak_atom.rb +20 -0
- data/lib/farce/engine/shared/weak_map/cell.rb +99 -0
- data/lib/farce/engine/shared/weak_map/index.rb +249 -0
- data/lib/farce/engine/shared/weak_map/lock.rb +80 -0
- data/lib/farce/engine/shared/weak_map/reference.rb +33 -0
- data/lib/farce/engine/shared.rb +63 -0
- data/lib/farce/engine/truffleruby/fiber_scheduler.rb +13 -0
- data/lib/farce/engine/truffleruby/lock.rb +121 -0
- data/lib/farce/engine/truffleruby/map.rb +656 -0
- data/lib/farce/engine/truffleruby/native/counter.rb +105 -0
- data/lib/farce/engine/truffleruby/native/flag.rb +77 -0
- data/lib/farce/engine/truffleruby/native/ordered_array_support.rb +67 -0
- data/lib/farce/engine/truffleruby/native/priority_queue.rb +388 -0
- data/lib/farce/engine/truffleruby/native/tree_map.rb +51 -0
- data/lib/farce/engine/truffleruby/native/unsafe_tree_map.rb +350 -0
- data/lib/farce/engine/truffleruby/signal.rb +77 -0
- data/lib/farce/engine/truffleruby.rb +148 -0
- data/lib/farce/envelope.rb +335 -0
- data/lib/farce/error.rb +35 -0
- data/lib/farce/exchanger.rb +41 -0
- data/lib/farce/flag.rb +27 -0
- data/lib/farce/integrations/active_support/blank.rb +68 -0
- data/lib/farce/integrations/active_support/clock.rb +17 -0
- data/lib/farce/integrations/active_support/duplicable.rb +78 -0
- data/lib/farce/integrations/active_support/map.rb +175 -0
- data/lib/farce/integrations/active_support/set.rb +60 -0
- data/lib/farce/integrations/active_support/value_serialization.rb +17 -0
- data/lib/farce/integrations/active_support/vector.rb +231 -0
- data/lib/farce/integrations/active_support.rb +9 -0
- data/lib/farce/integrations/activesupport.rb +5 -0
- data/lib/farce/integrations/bson.rb +108 -0
- data/lib/farce/integrations/cbor.rb +51 -0
- data/lib/farce/integrations/concurrent.rb +112 -0
- data/lib/farce/integrations/dry-types.rb +5 -0
- data/lib/farce/integrations/dry_types.rb +694 -0
- data/lib/farce/integrations/json.rb +7 -0
- data/lib/farce/integrations/msgpack.rb +112 -0
- data/lib/farce/integrations/oj.rb +69 -0
- data/lib/farce/integrations/psych.rb +191 -0
- data/lib/farce/integrations/ractor-sharing.rb +5 -0
- data/lib/farce/integrations/ractor-tmvar.rb +5 -0
- data/lib/farce/integrations/ractor_sharing.rb +172 -0
- data/lib/farce/integrations/ractor_tmvar.rb +64 -0
- data/lib/farce/integrations/shared/to_json.rb +42 -0
- data/lib/farce/integrations/sorted_set.rb +11 -0
- data/lib/farce/integrations/weakref.rb +38 -0
- data/lib/farce/integrations/yajl.rb +10 -0
- data/lib/farce/integrations.rb +156 -0
- data/lib/farce/internal/_frozen_config.rb +11 -0
- data/lib/farce/internal/autoloads.rb +47 -0
- data/lib/farce/internal/blocking_priority_queue.rb +122 -0
- data/lib/farce/internal/converter.rb +106 -0
- data/lib/farce/internal/copyable.rb +31 -0
- data/lib/farce/internal/delegation.rb +20 -0
- data/lib/farce/internal/external_transaction.rb +59 -0
- data/lib/farce/internal/fake_ractor.rb +179 -0
- data/lib/farce/internal/freeze.rb +118 -0
- data/lib/farce/internal/inspect.rb +157 -0
- data/lib/farce/internal/key_lock_map.rb +29 -0
- data/lib/farce/internal/key_normalizer.rb +289 -0
- data/lib/farce/internal/lease_initialization.rb +115 -0
- data/lib/farce/internal/lease_map.rb +441 -0
- data/lib/farce/internal/lease_pool_state.rb +228 -0
- data/lib/farce/internal/lease_state.rb +342 -0
- data/lib/farce/internal/lease_waiting.rb +13 -0
- data/lib/farce/internal/managed_queue.rb +26 -0
- data/lib/farce/internal/map_value_modes.rb +227 -0
- data/lib/farce/internal/marshal_support.rb +227 -0
- data/lib/farce/internal/mixin.rb +20 -0
- data/lib/farce/internal/mutable_ordered_key_lock_map.rb +63 -0
- data/lib/farce/internal/noncopyable.rb +17 -0
- data/lib/farce/internal/ordered_key_lock_map.rb +69 -0
- data/lib/farce/internal/pool_supervisor.rb +41 -0
- data/lib/farce/internal/pool_worker.rb +61 -0
- data/lib/farce/internal/portable_transaction/reservation_entry.rb +29 -0
- data/lib/farce/internal/portable_transaction/strong_map_entry.rb +137 -0
- data/lib/farce/internal/portable_transaction/strong_map_size_entry.rb +44 -0
- data/lib/farce/internal/portable_transaction/tree_entry.rb +64 -0
- data/lib/farce/internal/portable_transaction.rb +164 -0
- data/lib/farce/internal/proxy_owner_notifications.rb +29 -0
- data/lib/farce/internal/reservation_waiting.rb +24 -0
- data/lib/farce/internal/scheduled_task.rb +48 -0
- data/lib/farce/internal/scheduler_io.rb +171 -0
- data/lib/farce/internal/scheduler_lifecycle.rb +314 -0
- data/lib/farce/internal/select_scheduler.rb +235 -0
- data/lib/farce/internal/storage.rb +162 -0
- data/lib/farce/internal/strict_lease.rb +30 -0
- data/lib/farce/internal/strict_lease_map.rb +20 -0
- data/lib/farce/internal/strict_lease_pool.rb +29 -0
- data/lib/farce/internal/thread_pool.rb +166 -0
- data/lib/farce/internal/transaction_conflict.rb +9 -0
- data/lib/farce/internal/transaction_freeze_guard.rb +30 -0
- data/lib/farce/internal/transaction_map_snapshot.rb +123 -0
- data/lib/farce/internal/undefined.rb +22 -0
- data/lib/farce/internal/unshared_lease.rb +29 -0
- data/lib/farce/internal/unshared_lease_pool.rb +34 -0
- data/lib/farce/internal/unshared_queue_waiting.rb +28 -0
- data/lib/farce/internal/value_serialization.rb +13 -0
- data/lib/farce/internal/weak_map_value_modes.rb +58 -0
- data/lib/farce/internal/weak_mode_manager.rb +26 -0
- data/lib/farce/internal.rb +129 -0
- data/lib/farce/lazy.rb +100 -0
- data/lib/farce/lazy_ref.rb +40 -0
- data/lib/farce/lease.rb +28 -0
- data/lib/farce/lease_map.rb +34 -0
- data/lib/farce/lease_pool.rb +29 -0
- data/lib/farce/lfu_map.rb +53 -0
- data/lib/farce/local/atom.rb +23 -0
- data/lib/farce/local/counter.rb +88 -0
- data/lib/farce/local/flag.rb +65 -0
- data/lib/farce/local/lazy.rb +38 -0
- data/lib/farce/local/lazy_ref.rb +36 -0
- data/lib/farce/local/lease.rb +77 -0
- data/lib/farce/local/lease_map.rb +80 -0
- data/lib/farce/local/lease_pool.rb +38 -0
- data/lib/farce/local/lfu_map.rb +55 -0
- data/lib/farce/local/lru_map.rb +62 -0
- data/lib/farce/local/map.rb +47 -0
- data/lib/farce/local/molecule.rb +45 -0
- data/lib/farce/local/priority_queue.rb +53 -0
- data/lib/farce/local/queue.rb +32 -0
- data/lib/farce/local/scoped.rb +166 -0
- data/lib/farce/local/set.rb +18 -0
- data/lib/farce/local/sorted_set.rb +50 -0
- data/lib/farce/local/timer_queue.rb +41 -0
- data/lib/farce/local/tree_map.rb +47 -0
- data/lib/farce/local/vector.rb +30 -0
- data/lib/farce/local/weak_atom.rb +23 -0
- data/lib/farce/local/weak_key_map.rb +39 -0
- data/lib/farce/local/weak_map.rb +39 -0
- data/lib/farce/local/weak_set.rb +18 -0
- data/lib/farce/local/weak_value_map.rb +39 -0
- data/lib/farce/local.rb +35 -0
- data/lib/farce/lock.rb +54 -0
- data/lib/farce/lru_map.rb +63 -0
- data/lib/farce/map.rb +58 -0
- data/lib/farce/mode_manager.rb +142 -0
- data/lib/farce/molecule.rb +60 -0
- data/lib/farce/mutable.rb +171 -0
- data/lib/farce/pool.rb +332 -0
- data/lib/farce/port.rb +134 -0
- data/lib/farce/priority_queue.rb +70 -0
- data/lib/farce/proxy/register.rb +101 -0
- data/lib/farce/proxy/supervisor.rb +137 -0
- data/lib/farce/proxy/wrapper.rb +49 -0
- data/lib/farce/proxy.rb +291 -0
- data/lib/farce/queue.rb +60 -0
- data/lib/farce/ractor.rb +269 -0
- data/lib/farce/read_write_lock.rb +256 -0
- data/lib/farce/reference.rb +158 -0
- data/lib/farce/resolv/dns.rb +42 -0
- data/lib/farce/resolv.rb +85 -0
- data/lib/farce/scheduler.rb +536 -0
- data/lib/farce/set.rb +39 -0
- data/lib/farce/shareable.rb +150 -0
- data/lib/farce/signal.rb +97 -0
- data/lib/farce/sorted_set.rb +36 -0
- data/lib/farce/strict/atom.rb +34 -0
- data/lib/farce/strict/counter.rb +10 -0
- data/lib/farce/strict/exchanger.rb +25 -0
- data/lib/farce/strict/flag.rb +10 -0
- data/lib/farce/strict/lazy.rb +26 -0
- data/lib/farce/strict/lazy_ref.rb +26 -0
- data/lib/farce/strict/lease.rb +27 -0
- data/lib/farce/strict/lease_map.rb +33 -0
- data/lib/farce/strict/lease_pool.rb +28 -0
- data/lib/farce/strict/lfu_map.rb +27 -0
- data/lib/farce/strict/lru_map.rb +28 -0
- data/lib/farce/strict/map.rb +54 -0
- data/lib/farce/strict/molecule.rb +16 -0
- data/lib/farce/strict/port.rb +40 -0
- data/lib/farce/strict/priority_queue.rb +20 -0
- data/lib/farce/strict/queue.rb +17 -0
- data/lib/farce/strict/set.rb +14 -0
- data/lib/farce/strict/sorted_set.rb +19 -0
- data/lib/farce/strict/timer_queue.rb +13 -0
- data/lib/farce/strict/tree_map.rb +27 -0
- data/lib/farce/strict/vector.rb +24 -0
- data/lib/farce/strict/weak_atom.rb +31 -0
- data/lib/farce/strict/weak_key_map.rb +49 -0
- data/lib/farce/strict/weak_map.rb +49 -0
- data/lib/farce/strict/weak_set.rb +14 -0
- data/lib/farce/strict/weak_value_map.rb +48 -0
- data/lib/farce/strict.rb +28 -0
- data/lib/farce/system.rb +40 -0
- data/lib/farce/thread_scheduler.rb +70 -0
- data/lib/farce/timer_queue.rb +66 -0
- data/lib/farce/transaction/atom.rb +73 -0
- data/lib/farce/transaction/map.rb +25 -0
- data/lib/farce/transaction/map_operations.rb +143 -0
- data/lib/farce/transaction/molecule.rb +90 -0
- data/lib/farce/transaction/mutable.rb +61 -0
- data/lib/farce/transaction/set.rb +17 -0
- data/lib/farce/transaction/set_operations.rb +48 -0
- data/lib/farce/transaction/sorted_set.rb +18 -0
- data/lib/farce/transaction/tree_map.rb +78 -0
- data/lib/farce/transaction/vector.rb +139 -0
- data/lib/farce/transaction/wrapper.rb +202 -0
- data/lib/farce/transaction.rb +343 -0
- data/lib/farce/tree_map.rb +56 -0
- data/lib/farce/unsafe/lfu_map.rb +36 -0
- data/lib/farce/unsafe/lru_map.rb +36 -0
- data/lib/farce/unsafe/tree_map.rb +21 -0
- data/lib/farce/unsafe.rb +29 -0
- data/lib/farce/unshareable.rb +67 -0
- data/lib/farce/unshared/atom.rb +24 -0
- data/lib/farce/unshared/counter.rb +10 -0
- data/lib/farce/unshared/flag.rb +10 -0
- data/lib/farce/unshared/lazy.rb +38 -0
- data/lib/farce/unshared/lazy_ref.rb +26 -0
- data/lib/farce/unshared/lease.rb +27 -0
- data/lib/farce/unshared/lease_map.rb +26 -0
- data/lib/farce/unshared/lease_pool.rb +25 -0
- data/lib/farce/unshared/lfu_map.rb +20 -0
- data/lib/farce/unshared/lru_map.rb +20 -0
- data/lib/farce/unshared/map.rb +49 -0
- data/lib/farce/unshared/molecule.rb +16 -0
- data/lib/farce/unshared/priority_queue.rb +16 -0
- data/lib/farce/unshared/queue.rb +27 -0
- data/lib/farce/unshared/set.rb +14 -0
- data/lib/farce/unshared/sorted_set.rb +28 -0
- data/lib/farce/unshared/timer_queue.rb +16 -0
- data/lib/farce/unshared/tree_map.rb +21 -0
- data/lib/farce/unshared/vector.rb +19 -0
- data/lib/farce/unshared/weak_atom.rb +31 -0
- data/lib/farce/unshared/weak_key_map.rb +44 -0
- data/lib/farce/unshared/weak_map.rb +44 -0
- data/lib/farce/unshared/weak_set.rb +14 -0
- data/lib/farce/unshared/weak_value_map.rb +43 -0
- data/lib/farce/unshared.rb +28 -0
- data/lib/farce/vector.rb +228 -0
- data/lib/farce/version.rb +8 -0
- data/lib/farce/walker/definitions.rb +186 -0
- data/lib/farce/walker/modification.rb +355 -0
- data/lib/farce/walker.rb +319 -0
- data/lib/farce/weak_atom.rb +121 -0
- data/lib/farce/weak_key_map.rb +31 -0
- data/lib/farce/weak_map.rb +33 -0
- data/lib/farce/weak_ref.rb +67 -0
- data/lib/farce/weak_set.rb +82 -0
- data/lib/farce/weak_value.rb +195 -0
- data/lib/farce/weak_value_map.rb +32 -0
- data/lib/farce.rb +519 -0
- metadata +468 -0
data/ext/farce/reactor.h
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#ifndef FARCE_FIBER_REACTOR_H
|
|
2
|
+
#define FARCE_FIBER_REACTOR_H
|
|
3
|
+
#include <ruby.h>
|
|
4
|
+
#include <ruby/io.h>
|
|
5
|
+
#include <ruby/io/buffer.h>
|
|
6
|
+
#include <ruby/thread.h>
|
|
7
|
+
#include <ruby/st.h>
|
|
8
|
+
#include <pthread.h>
|
|
9
|
+
#include <stdint.h>
|
|
10
|
+
#include <time.h>
|
|
11
|
+
#include <sys/stat.h>
|
|
12
|
+
#if defined(FARCE_HAVE_LIBURING)
|
|
13
|
+
#include <liburing.h>
|
|
14
|
+
#define FARCE_URING 1
|
|
15
|
+
#endif
|
|
16
|
+
#ifdef HAVE_SYS_EVENT_H
|
|
17
|
+
#include <sys/event.h>
|
|
18
|
+
#endif
|
|
19
|
+
#define FS_READ 1
|
|
20
|
+
#define FS_PRI 2
|
|
21
|
+
#define FS_WRITE 4
|
|
22
|
+
#define FS_EVENTS 1024
|
|
23
|
+
#define FS_RECEIVE (UINT64_C(1) << 63)
|
|
24
|
+
#define FS_SLOT_BITS 20
|
|
25
|
+
#define FS_SLOT_MASK ((1U << FS_SLOT_BITS) - 1)
|
|
26
|
+
|
|
27
|
+
typedef struct fs_admission fs_admission;
|
|
28
|
+
struct fs_admission { VALUE parent, child; fs_admission *previous; };
|
|
29
|
+
typedef struct fs_wait fs_wait;
|
|
30
|
+
typedef struct { fs_wait *wait; uint64_t generation; uint32_t next_free; } fs_slot;
|
|
31
|
+
typedef struct fs_reg fs_reg;
|
|
32
|
+
typedef struct fs_watch fs_watch;
|
|
33
|
+
struct fs_watch {
|
|
34
|
+
fs_wait *wait;
|
|
35
|
+
fs_reg *reg;
|
|
36
|
+
fs_watch *next_reg, *next_wait;
|
|
37
|
+
int events, group;
|
|
38
|
+
long index;
|
|
39
|
+
};
|
|
40
|
+
struct fs_reg {
|
|
41
|
+
int fd, events, poll_events;
|
|
42
|
+
uint64_t generation;
|
|
43
|
+
fs_watch *watches;
|
|
44
|
+
};
|
|
45
|
+
struct fs_wait {
|
|
46
|
+
VALUE token, fiber, value, error, groups, ios;
|
|
47
|
+
uint32_t slot;
|
|
48
|
+
int status, events, selected, queued, native_error, receive_pending;
|
|
49
|
+
fs_wait *ready_next, *ready_prev;
|
|
50
|
+
fs_watch *watches;
|
|
51
|
+
fs_watch first_watch;
|
|
52
|
+
};
|
|
53
|
+
typedef struct { uint64_t generation; int events, error; } fs_event;
|
|
54
|
+
typedef struct {
|
|
55
|
+
VALUE owner, root, active, backend, fallback;
|
|
56
|
+
fs_wait *ready_head, *ready_tail;
|
|
57
|
+
fs_admission *admission;
|
|
58
|
+
int dispatch_left, stopping, closing, policy_pending, allow_poll;
|
|
59
|
+
st_table *fibers, *regs, *generations, *retired_regs;
|
|
60
|
+
fs_slot *slots;
|
|
61
|
+
uint32_t slot_count, slot_capacity, first_free;
|
|
62
|
+
size_t pending;
|
|
63
|
+
uint64_t serial, generation, suspensions;
|
|
64
|
+
unsigned immediate;
|
|
65
|
+
int selected_pending, receive_disabled;
|
|
66
|
+
int driver, descriptor, wake[2], closed;
|
|
67
|
+
pthread_mutex_t wake_mutex;
|
|
68
|
+
#ifdef FARCE_URING
|
|
69
|
+
struct io_uring ring;
|
|
70
|
+
int ring_live;
|
|
71
|
+
#endif
|
|
72
|
+
#ifdef HAVE_SYS_EVENT_H
|
|
73
|
+
struct kevent *changes;
|
|
74
|
+
int change_count, change_capacity;
|
|
75
|
+
#endif
|
|
76
|
+
fs_event events[FS_EVENTS];
|
|
77
|
+
double timeout, close_check_at;
|
|
78
|
+
int event_count, poll_error, polling_regs, ready_batches;
|
|
79
|
+
} fs_state;
|
|
80
|
+
enum { FS_EPOLL = 1, FS_KQUEUE, FS_URING_DRIVER };
|
|
81
|
+
extern const rb_data_type_t fs_type;
|
|
82
|
+
static inline fs_state *fs_get(VALUE self) {
|
|
83
|
+
fs_state *s; TypedData_Get_Struct(self, fs_state, &fs_type, s); return s;
|
|
84
|
+
}
|
|
85
|
+
int fs_driver_init(fs_state *s, int driver);
|
|
86
|
+
int fs_driver_update(fs_state *s, fs_reg *reg, int events);
|
|
87
|
+
int fs_driver_receive(fs_state *s, fs_wait *w, int fd, void *buffer, size_t size);
|
|
88
|
+
void fs_cancel_receive(VALUE self, fs_wait *w);
|
|
89
|
+
void fs_driver_close(fs_state *s);
|
|
90
|
+
void *fs_driver_poll(void *data);
|
|
91
|
+
void fs_check_fiber(VALUE self);
|
|
92
|
+
VALUE fs_checkpoint(VALUE self, VALUE value);
|
|
93
|
+
VALUE fs_arm(VALUE self);
|
|
94
|
+
VALUE fs_arm_checked(VALUE self);
|
|
95
|
+
VALUE fs_suspend(VALUE self, VALUE token);
|
|
96
|
+
VALUE fs_park(VALUE self, VALUE token);
|
|
97
|
+
VALUE fs_retire(VALUE self, VALUE token);
|
|
98
|
+
VALUE fs_resume(VALUE self, VALUE token, VALUE value, VALUE error);
|
|
99
|
+
void fs_watch_io(fs_state *s, fs_wait *wait, int fd, int events, int group, long index);
|
|
100
|
+
fs_wait *fs_lookup(fs_state *s, VALUE token);
|
|
101
|
+
VALUE fs_io_wait(int argc, VALUE *argv, VALUE self);
|
|
102
|
+
void fs_init_io(VALUE klass);
|
|
103
|
+
#endif
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#ifndef FARCE_SHAREABLE_H
|
|
2
|
+
#define FARCE_SHAREABLE_H
|
|
3
|
+
|
|
4
|
+
#include "ruby.h"
|
|
5
|
+
#include "ruby/ractor.h"
|
|
6
|
+
#include "ruby/version.h"
|
|
7
|
+
|
|
8
|
+
/* CRuby 4.0 declares rb_obj_set_shareable in its public header, but some
|
|
9
|
+
* installations do not export the symbol. The raw fallback is limited to the
|
|
10
|
+
* audited 3.4/4.0 object layout. CRuby 4.1 must use the exported function so
|
|
11
|
+
* global-GC and shared-reference bookkeeping run. */
|
|
12
|
+
static inline VALUE
|
|
13
|
+
farce_ruby_mark_shareable(VALUE object)
|
|
14
|
+
{
|
|
15
|
+
#if defined(FARCE_HAVE_EXPORTED_SHAREABLE_MARKER)
|
|
16
|
+
# if RUBY_API_VERSION_CODE < 40100
|
|
17
|
+
# error "The exported shareable marker is enabled only for CRuby 4.1 or newer"
|
|
18
|
+
# endif
|
|
19
|
+
return RB_OBJ_SET_SHAREABLE(object);
|
|
20
|
+
#elif defined(FARCE_USE_LEGACY_SHAREABLE_FLAG)
|
|
21
|
+
# if RUBY_API_VERSION_CODE < 30400 || RUBY_API_VERSION_CODE >= 40100
|
|
22
|
+
# error "The legacy shareable flag is supported only on CRuby 3.4 and 4.0"
|
|
23
|
+
# endif
|
|
24
|
+
RB_FL_SET_RAW(object, RUBY_FL_SHAREABLE);
|
|
25
|
+
return object;
|
|
26
|
+
#else
|
|
27
|
+
# error "No supported CRuby shareable marker was configured"
|
|
28
|
+
#endif
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#endif
|
data/ext/farce/signal.c
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
#include "containers.h"
|
|
2
|
+
#include "ruby/io.h"
|
|
3
|
+
|
|
4
|
+
#include <errno.h>
|
|
5
|
+
#include <fcntl.h>
|
|
6
|
+
#include <math.h>
|
|
7
|
+
#include <stdint.h>
|
|
8
|
+
#include <time.h>
|
|
9
|
+
#include <unistd.h>
|
|
10
|
+
|
|
11
|
+
static VALUE cSignal;
|
|
12
|
+
|
|
13
|
+
typedef struct containers_signal_waiter containers_signal_waiter_t;
|
|
14
|
+
|
|
15
|
+
struct containers_signal_waiter {
|
|
16
|
+
int read_fd;
|
|
17
|
+
int write_fd;
|
|
18
|
+
bool notified;
|
|
19
|
+
containers_signal_waiter_t *next;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
typedef struct {
|
|
23
|
+
pthread_mutex_t lock;
|
|
24
|
+
containers_signal_waiter_t *waiters;
|
|
25
|
+
uint64_t generation;
|
|
26
|
+
bool initialized;
|
|
27
|
+
} containers_signal_t;
|
|
28
|
+
|
|
29
|
+
typedef struct {
|
|
30
|
+
bool finite;
|
|
31
|
+
double deadline;
|
|
32
|
+
} containers_signal_timeout_t;
|
|
33
|
+
|
|
34
|
+
typedef struct {
|
|
35
|
+
containers_signal_t *signal;
|
|
36
|
+
containers_signal_waiter_t waiter;
|
|
37
|
+
containers_signal_timeout_t *timeout;
|
|
38
|
+
} containers_signal_wait_context_t;
|
|
39
|
+
|
|
40
|
+
static double
|
|
41
|
+
containers_signal_monotonic_now(void)
|
|
42
|
+
{
|
|
43
|
+
struct timespec now;
|
|
44
|
+
#ifdef CLOCK_MONOTONIC
|
|
45
|
+
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) {
|
|
46
|
+
return (double)now.tv_sec + (double)now.tv_nsec / 1000000000.0;
|
|
47
|
+
}
|
|
48
|
+
#endif
|
|
49
|
+
struct timeval fallback;
|
|
50
|
+
gettimeofday(&fallback, NULL);
|
|
51
|
+
return (double)fallback.tv_sec + (double)fallback.tv_usec / 1000000.0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static containers_signal_timeout_t
|
|
55
|
+
containers_signal_parse_timeout(VALUE value)
|
|
56
|
+
{
|
|
57
|
+
containers_signal_timeout_t timeout = {.finite = false, .deadline = 0};
|
|
58
|
+
if (NIL_P(value)) return timeout;
|
|
59
|
+
|
|
60
|
+
double seconds = NUM2DBL(value);
|
|
61
|
+
if (!isfinite(seconds) || seconds < 0) {
|
|
62
|
+
rb_raise(rb_eArgError, "timeout must be a finite, non-negative number or nil");
|
|
63
|
+
}
|
|
64
|
+
timeout.finite = true;
|
|
65
|
+
timeout.deadline = containers_signal_monotonic_now() + seconds;
|
|
66
|
+
return timeout;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static void
|
|
70
|
+
containers_signal_set_fd_flags(int fd)
|
|
71
|
+
{
|
|
72
|
+
#ifdef _WIN32
|
|
73
|
+
(void)fd;
|
|
74
|
+
#else
|
|
75
|
+
int flags = fcntl(fd, F_GETFL, 0);
|
|
76
|
+
if (flags >= 0) (void)fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
|
77
|
+
flags = fcntl(fd, F_GETFD, 0);
|
|
78
|
+
if (flags >= 0) (void)fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
|
|
79
|
+
#endif
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Called with signal->lock held. Each waiter has a separate descriptor, so a
|
|
83
|
+
* single broadcast makes every scheduled Fiber or native thread runnable. */
|
|
84
|
+
static void
|
|
85
|
+
containers_signal_notify_waiters_locked(containers_signal_t *signal)
|
|
86
|
+
{
|
|
87
|
+
unsigned char byte = 1;
|
|
88
|
+
for (containers_signal_waiter_t *waiter = signal->waiters; waiter; waiter = waiter->next) {
|
|
89
|
+
if (waiter->notified) continue;
|
|
90
|
+
ssize_t result;
|
|
91
|
+
do {
|
|
92
|
+
result = write(waiter->write_fd, &byte, 1);
|
|
93
|
+
} while (result < 0 && errno == EINTR);
|
|
94
|
+
if (result == 1 || (result < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))) {
|
|
95
|
+
waiter->notified = true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
static void
|
|
101
|
+
containers_signal_free(void *pointer)
|
|
102
|
+
{
|
|
103
|
+
containers_signal_t *signal = pointer;
|
|
104
|
+
pthread_mutex_destroy(&signal->lock);
|
|
105
|
+
ruby_xfree(signal);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static size_t
|
|
109
|
+
containers_signal_memsize(const void *pointer)
|
|
110
|
+
{
|
|
111
|
+
return pointer ? sizeof(containers_signal_t) : 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static const rb_data_type_t containers_signal_type = {
|
|
115
|
+
.wrap_struct_name = "Ractor::Containers::Signal",
|
|
116
|
+
.function = {
|
|
117
|
+
.dmark = NULL,
|
|
118
|
+
.dfree = containers_signal_free,
|
|
119
|
+
.dsize = containers_signal_memsize,
|
|
120
|
+
.dcompact = NULL,
|
|
121
|
+
},
|
|
122
|
+
.flags = RUBY_TYPED_FROZEN_SHAREABLE,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
static VALUE
|
|
126
|
+
containers_signal_allocate(VALUE klass)
|
|
127
|
+
{
|
|
128
|
+
containers_signal_t *signal;
|
|
129
|
+
VALUE object = TypedData_Make_Struct(
|
|
130
|
+
klass,
|
|
131
|
+
containers_signal_t,
|
|
132
|
+
&containers_signal_type,
|
|
133
|
+
signal
|
|
134
|
+
);
|
|
135
|
+
pthread_mutex_init(&signal->lock, NULL);
|
|
136
|
+
signal->waiters = NULL;
|
|
137
|
+
signal->generation = 0;
|
|
138
|
+
signal->initialized = false;
|
|
139
|
+
return object;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
static containers_signal_t *
|
|
143
|
+
containers_signal_get(VALUE self)
|
|
144
|
+
{
|
|
145
|
+
containers_signal_t *signal;
|
|
146
|
+
TypedData_Get_Struct(self, containers_signal_t, &containers_signal_type, signal);
|
|
147
|
+
if (!signal->initialized) rb_raise(rb_eRuntimeError, "uninitialized Signal");
|
|
148
|
+
return signal;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static VALUE
|
|
152
|
+
containers_signal_frozen_p(VALUE self)
|
|
153
|
+
{
|
|
154
|
+
(void)self;
|
|
155
|
+
return Qfalse;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static VALUE
|
|
159
|
+
containers_signal_freeze(VALUE self)
|
|
160
|
+
{
|
|
161
|
+
containers_raise_unfreezable(self);
|
|
162
|
+
return Qnil;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static VALUE
|
|
166
|
+
containers_signal_initialize(VALUE self)
|
|
167
|
+
{
|
|
168
|
+
containers_signal_t *signal;
|
|
169
|
+
TypedData_Get_Struct(self, containers_signal_t, &containers_signal_type, signal);
|
|
170
|
+
if (signal->initialized) rb_raise(rb_eRuntimeError, "Signal is already initialized");
|
|
171
|
+
signal->initialized = true;
|
|
172
|
+
containers_publish_native_reference_free(self);
|
|
173
|
+
return self;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
VALUE
|
|
177
|
+
containers_signal_new(void)
|
|
178
|
+
{
|
|
179
|
+
VALUE signal = containers_signal_allocate(cSignal);
|
|
180
|
+
return containers_signal_initialize(signal);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
static bool
|
|
184
|
+
containers_signal_wait_for_descriptor(int fd, containers_signal_timeout_t *timeout)
|
|
185
|
+
{
|
|
186
|
+
VALUE wait_timeout = Qnil;
|
|
187
|
+
if (timeout->finite) {
|
|
188
|
+
double remaining = timeout->deadline - containers_signal_monotonic_now();
|
|
189
|
+
if (remaining <= 0) return false;
|
|
190
|
+
wait_timeout = DBL2NUM(remaining);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return containers_wait_for_readable(fd, wait_timeout);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
static VALUE
|
|
197
|
+
containers_signal_wait_body(VALUE opaque)
|
|
198
|
+
{
|
|
199
|
+
containers_signal_wait_context_t *context = (containers_signal_wait_context_t *)opaque;
|
|
200
|
+
return containers_signal_wait_for_descriptor(context->waiter.read_fd, context->timeout)
|
|
201
|
+
? Qtrue
|
|
202
|
+
: Qfalse;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
static VALUE
|
|
206
|
+
containers_signal_wait_cleanup(VALUE opaque)
|
|
207
|
+
{
|
|
208
|
+
containers_signal_wait_context_t *context = (containers_signal_wait_context_t *)opaque;
|
|
209
|
+
containers_signal_waiter_t **link;
|
|
210
|
+
|
|
211
|
+
pthread_mutex_lock(&context->signal->lock);
|
|
212
|
+
for (link = &context->signal->waiters; *link; link = &(*link)->next) {
|
|
213
|
+
if (*link == &context->waiter) {
|
|
214
|
+
*link = context->waiter.next;
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
pthread_mutex_unlock(&context->signal->lock);
|
|
219
|
+
close(context->waiter.read_fd);
|
|
220
|
+
close(context->waiter.write_fd);
|
|
221
|
+
return Qnil;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* Called with signal->lock held and always returns with it released. */
|
|
225
|
+
static bool
|
|
226
|
+
containers_signal_wait_once(
|
|
227
|
+
containers_signal_t *signal,
|
|
228
|
+
containers_signal_timeout_t *timeout
|
|
229
|
+
)
|
|
230
|
+
{
|
|
231
|
+
int descriptors[2];
|
|
232
|
+
if (pipe(descriptors) != 0) {
|
|
233
|
+
pthread_mutex_unlock(&signal->lock);
|
|
234
|
+
rb_sys_fail("pipe");
|
|
235
|
+
}
|
|
236
|
+
containers_signal_set_fd_flags(descriptors[0]);
|
|
237
|
+
containers_signal_set_fd_flags(descriptors[1]);
|
|
238
|
+
|
|
239
|
+
containers_signal_wait_context_t context = {
|
|
240
|
+
.signal = signal,
|
|
241
|
+
.waiter = {
|
|
242
|
+
.read_fd = descriptors[0],
|
|
243
|
+
.write_fd = descriptors[1],
|
|
244
|
+
.notified = false,
|
|
245
|
+
.next = signal->waiters,
|
|
246
|
+
},
|
|
247
|
+
.timeout = timeout,
|
|
248
|
+
};
|
|
249
|
+
signal->waiters = &context.waiter;
|
|
250
|
+
pthread_mutex_unlock(&signal->lock);
|
|
251
|
+
return RTEST(rb_ensure(
|
|
252
|
+
containers_signal_wait_body,
|
|
253
|
+
(VALUE)&context,
|
|
254
|
+
containers_signal_wait_cleanup,
|
|
255
|
+
(VALUE)&context
|
|
256
|
+
));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
static VALUE
|
|
260
|
+
containers_signal_timeout_result(void)
|
|
261
|
+
{
|
|
262
|
+
return rb_block_given_p() ? rb_yield_values(0) : Qnil;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
static VALUE
|
|
266
|
+
containers_signal_generation(VALUE self)
|
|
267
|
+
{
|
|
268
|
+
containers_signal_t *signal = containers_signal_get(self);
|
|
269
|
+
uint64_t generation;
|
|
270
|
+
pthread_mutex_lock(&signal->lock);
|
|
271
|
+
generation = signal->generation;
|
|
272
|
+
pthread_mutex_unlock(&signal->lock);
|
|
273
|
+
return ULL2NUM(generation);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
static VALUE
|
|
277
|
+
containers_signal_num_waiting(VALUE self)
|
|
278
|
+
{
|
|
279
|
+
containers_signal_t *signal = containers_signal_get(self);
|
|
280
|
+
size_t count = 0;
|
|
281
|
+
|
|
282
|
+
/* Count on demand so wait and broadcast have no additional bookkeeping. */
|
|
283
|
+
pthread_mutex_lock(&signal->lock);
|
|
284
|
+
for (containers_signal_waiter_t *waiter = signal->waiters; waiter; waiter = waiter->next) {
|
|
285
|
+
count++;
|
|
286
|
+
}
|
|
287
|
+
pthread_mutex_unlock(&signal->lock);
|
|
288
|
+
return SIZET2NUM(count);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
VALUE
|
|
292
|
+
containers_signal_broadcast(VALUE self)
|
|
293
|
+
{
|
|
294
|
+
containers_signal_t *signal = containers_signal_get(self);
|
|
295
|
+
uint64_t generation;
|
|
296
|
+
pthread_mutex_lock(&signal->lock);
|
|
297
|
+
signal->generation++;
|
|
298
|
+
generation = signal->generation;
|
|
299
|
+
containers_signal_notify_waiters_locked(signal);
|
|
300
|
+
pthread_mutex_unlock(&signal->lock);
|
|
301
|
+
return ULL2NUM(generation);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
static VALUE
|
|
305
|
+
containers_signal_wait(int argc, VALUE *argv, VALUE self)
|
|
306
|
+
{
|
|
307
|
+
VALUE observed_value = Qnil;
|
|
308
|
+
VALUE keywords = Qnil;
|
|
309
|
+
VALUE keyword_values[1] = {Qundef};
|
|
310
|
+
ID keyword_ids[] = {rb_intern("timeout")};
|
|
311
|
+
rb_scan_args(argc, argv, "01:", &observed_value, &keywords);
|
|
312
|
+
if (!NIL_P(keywords)) rb_get_kwargs(keywords, keyword_ids, 0, 1, keyword_values);
|
|
313
|
+
|
|
314
|
+
bool snapshot_at_entry = NIL_P(observed_value);
|
|
315
|
+
uint64_t observed = snapshot_at_entry ? 0 : NUM2ULL(observed_value);
|
|
316
|
+
containers_signal_timeout_t timeout = containers_signal_parse_timeout(
|
|
317
|
+
keyword_values[0] == Qundef ? Qnil : keyword_values[0]
|
|
318
|
+
);
|
|
319
|
+
containers_signal_t *signal = containers_signal_get(self);
|
|
320
|
+
|
|
321
|
+
pthread_mutex_lock(&signal->lock);
|
|
322
|
+
if (snapshot_at_entry) observed = signal->generation;
|
|
323
|
+
for (;;) {
|
|
324
|
+
if (signal->generation != observed) {
|
|
325
|
+
uint64_t generation = signal->generation;
|
|
326
|
+
pthread_mutex_unlock(&signal->lock);
|
|
327
|
+
return ULL2NUM(generation);
|
|
328
|
+
}
|
|
329
|
+
bool awakened = containers_signal_wait_once(signal, &timeout);
|
|
330
|
+
pthread_mutex_lock(&signal->lock);
|
|
331
|
+
if (!awakened && signal->generation == observed) {
|
|
332
|
+
pthread_mutex_unlock(&signal->lock);
|
|
333
|
+
return containers_signal_timeout_result();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
void
|
|
339
|
+
containers_init_signal(VALUE namespace)
|
|
340
|
+
{
|
|
341
|
+
cSignal = rb_define_class_under(namespace, "Signal", rb_cObject);
|
|
342
|
+
rb_define_alloc_func(cSignal, containers_signal_allocate);
|
|
343
|
+
rb_define_method(cSignal, "initialize", containers_signal_initialize, 0);
|
|
344
|
+
rb_define_method(cSignal, "generation", containers_signal_generation, 0);
|
|
345
|
+
rb_define_method(cSignal, "num_waiting", containers_signal_num_waiting, 0);
|
|
346
|
+
rb_define_method(cSignal, "broadcast", containers_signal_broadcast, 0);
|
|
347
|
+
rb_define_method(cSignal, "wait", containers_signal_wait, -1);
|
|
348
|
+
rb_define_method(cSignal, "freeze", containers_signal_freeze, 0);
|
|
349
|
+
rb_define_method(cSignal, "frozen?", containers_signal_frozen_p, 0);
|
|
350
|
+
}
|