farce 0 → 0.1.0
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 +4 -4
- data/CHANGELOG.md +9 -0
- data/CODE_OF_CONDUCT.md +26 -0
- data/CONTRIBUTING.md +71 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1525 -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/fiber_scheduler.rb +20 -0
- data/lib/farce/engine/ruby/3.4/port.rb +186 -0
- data/lib/farce/engine/ruby/3.4/ractor_methods.rb +26 -0
- data/lib/farce/engine/ruby/3.4/ractor_selector.rb +92 -0
- data/lib/farce/engine/ruby/3.4/vault.rb +56 -0
- data/lib/farce/engine/ruby/4.0/port.rb +19 -0
- data/lib/farce/engine/ruby/4.0/ractor_methods.rb +20 -0
- data/lib/farce/engine/ruby/4.0/ractor_selector.rb +108 -0
- data/lib/farce/engine/ruby/4.0/vault.rb +74 -0
- data/lib/farce/engine/ruby/4.1/port.rb +21 -0
- data/lib/farce/engine/ruby/4.1/ractor_methods.rb +22 -0
- data/lib/farce/engine/ruby/4.1/ractor_selector.rb +25 -0
- data/lib/farce/engine/ruby/4.1/vault.rb +5 -0
- data/lib/farce/engine/ruby/fiber_scheduler.rb +32 -0
- data/lib/farce/engine/ruby/key_lock_map.rb +28 -0
- data/lib/farce/engine/ruby/shared/lease.rb +26 -0
- data/lib/farce/engine/ruby/shared/lease_pool.rb +24 -0
- data/lib/farce/engine/ruby/shared/main_scheduler.rb +9 -0
- data/lib/farce/engine/ruby/shared/parallel_scheduler.rb +9 -0
- data/lib/farce/engine/ruby/shared/proxy_owner.rb +31 -0
- data/lib/farce/engine/ruby/shared/ractor_methods.rb +34 -0
- data/lib/farce/engine/ruby/shared/ractor_selector.rb +328 -0
- data/lib/farce/engine/ruby/shared/strict_map.rb +13 -0
- data/lib/farce/engine/ruby/shared/unshared_vector.rb +14 -0
- data/lib/farce/engine/ruby/shared/vault.rb +144 -0
- data/lib/farce/engine/ruby/shared/vault_weak_map.rb +336 -0
- data/lib/farce/engine/ruby/shared/weak_atom.rb +54 -0
- data/lib/farce/engine/ruby/shared/weak_map.rb +413 -0
- data/lib/farce/engine/ruby.rb +130 -0
- data/lib/farce/engine/shared/atom.rb +10 -0
- data/lib/farce/engine/shared/exchanger.rb +130 -0
- data/lib/farce/engine/shared/identity_key.rb +22 -0
- data/lib/farce/engine/shared/lease.rb +10 -0
- data/lib/farce/engine/shared/lease_pool.rb +10 -0
- data/lib/farce/engine/shared/main_scheduler.rb +20 -0
- data/lib/farce/engine/shared/map_key_coordination.rb +226 -0
- data/lib/farce/engine/shared/parallel_scheduler.rb +9 -0
- data/lib/farce/engine/shared/port.rb +44 -0
- data/lib/farce/engine/shared/portable_bounded_map.rb +619 -0
- data/lib/farce/engine/shared/proxy_owner.rb +43 -0
- data/lib/farce/engine/shared/queue.rb +233 -0
- data/lib/farce/engine/shared/ractor_methods.rb +73 -0
- data/lib/farce/engine/shared/rebindable.rb +15 -0
- data/lib/farce/engine/shared/strict_atom.rb +73 -0
- data/lib/farce/engine/shared/strict_map.rb +117 -0
- data/lib/farce/engine/shared/strict_queue_values.rb +27 -0
- data/lib/farce/engine/shared/strict_tree_map.rb +56 -0
- data/lib/farce/engine/shared/transaction_map_backend.rb +20 -0
- data/lib/farce/engine/shared/trie.rb +317 -0
- data/lib/farce/engine/shared/trie_builder.rb +199 -0
- data/lib/farce/engine/shared/unshareable.rb +14 -0
- data/lib/farce/engine/shared/unshared_atom.rb +256 -0
- data/lib/farce/engine/shared/unshared_priority_queue.rb +9 -0
- data/lib/farce/engine/shared/unshared_queue.rb +18 -0
- data/lib/farce/engine/shared/unshared_signal.rb +21 -0
- data/lib/farce/engine/shared/unshared_vector.rb +377 -0
- data/lib/farce/engine/shared/unshared_weak_atom.rb +30 -0
- data/lib/farce/engine/shared/unshared_weak_map.rb +445 -0
- data/lib/farce/engine/shared/vault.rb +31 -0
- data/lib/farce/engine/shared/vector.rb +83 -0
- data/lib/farce/engine/shared/weak_atom/base.rb +189 -0
- data/lib/farce/engine/shared/weak_atom.rb +20 -0
- data/lib/farce/engine/shared/weak_map/cell.rb +99 -0
- data/lib/farce/engine/shared/weak_map/index.rb +249 -0
- data/lib/farce/engine/shared/weak_map/lock.rb +80 -0
- data/lib/farce/engine/shared/weak_map/reference.rb +33 -0
- data/lib/farce/engine/shared.rb +63 -0
- data/lib/farce/engine/truffleruby/fiber_scheduler.rb +13 -0
- data/lib/farce/engine/truffleruby/lock.rb +121 -0
- data/lib/farce/engine/truffleruby/map.rb +656 -0
- data/lib/farce/engine/truffleruby/native/counter.rb +105 -0
- data/lib/farce/engine/truffleruby/native/flag.rb +77 -0
- data/lib/farce/engine/truffleruby/native/ordered_array_support.rb +67 -0
- data/lib/farce/engine/truffleruby/native/priority_queue.rb +388 -0
- data/lib/farce/engine/truffleruby/native/tree_map.rb +51 -0
- data/lib/farce/engine/truffleruby/native/unsafe_tree_map.rb +350 -0
- data/lib/farce/engine/truffleruby/signal.rb +77 -0
- data/lib/farce/engine/truffleruby.rb +148 -0
- data/lib/farce/envelope.rb +335 -0
- data/lib/farce/error.rb +35 -0
- data/lib/farce/exchanger.rb +41 -0
- data/lib/farce/flag.rb +27 -0
- data/lib/farce/integrations/active_support/blank.rb +68 -0
- data/lib/farce/integrations/active_support/clock.rb +17 -0
- data/lib/farce/integrations/active_support/duplicable.rb +78 -0
- data/lib/farce/integrations/active_support/map.rb +175 -0
- data/lib/farce/integrations/active_support/set.rb +60 -0
- data/lib/farce/integrations/active_support/value_serialization.rb +17 -0
- data/lib/farce/integrations/active_support/vector.rb +231 -0
- data/lib/farce/integrations/active_support.rb +9 -0
- data/lib/farce/integrations/activesupport.rb +5 -0
- data/lib/farce/integrations/bson.rb +108 -0
- data/lib/farce/integrations/cbor.rb +51 -0
- data/lib/farce/integrations/concurrent.rb +112 -0
- data/lib/farce/integrations/dry-types.rb +5 -0
- data/lib/farce/integrations/dry_types.rb +694 -0
- data/lib/farce/integrations/json.rb +7 -0
- data/lib/farce/integrations/msgpack.rb +112 -0
- data/lib/farce/integrations/oj.rb +69 -0
- data/lib/farce/integrations/psych.rb +191 -0
- data/lib/farce/integrations/ractor-sharing.rb +5 -0
- data/lib/farce/integrations/ractor-tmvar.rb +5 -0
- data/lib/farce/integrations/ractor_sharing.rb +172 -0
- data/lib/farce/integrations/ractor_tmvar.rb +64 -0
- data/lib/farce/integrations/shared/to_json.rb +42 -0
- data/lib/farce/integrations/sorted_set.rb +11 -0
- data/lib/farce/integrations/weakref.rb +38 -0
- data/lib/farce/integrations/yajl.rb +10 -0
- data/lib/farce/integrations.rb +156 -0
- data/lib/farce/internal/_frozen_config.rb +11 -0
- data/lib/farce/internal/autoloads.rb +47 -0
- data/lib/farce/internal/blocking_priority_queue.rb +122 -0
- data/lib/farce/internal/converter.rb +106 -0
- data/lib/farce/internal/copyable.rb +31 -0
- data/lib/farce/internal/delegation.rb +20 -0
- data/lib/farce/internal/external_transaction.rb +59 -0
- data/lib/farce/internal/fake_ractor.rb +179 -0
- data/lib/farce/internal/freeze.rb +118 -0
- data/lib/farce/internal/inspect.rb +157 -0
- data/lib/farce/internal/key_lock_map.rb +29 -0
- data/lib/farce/internal/key_normalizer.rb +289 -0
- data/lib/farce/internal/lease_initialization.rb +115 -0
- data/lib/farce/internal/lease_map.rb +441 -0
- data/lib/farce/internal/lease_pool_state.rb +228 -0
- data/lib/farce/internal/lease_state.rb +342 -0
- data/lib/farce/internal/lease_waiting.rb +13 -0
- data/lib/farce/internal/managed_queue.rb +26 -0
- data/lib/farce/internal/map_value_modes.rb +227 -0
- data/lib/farce/internal/marshal_support.rb +227 -0
- data/lib/farce/internal/mixin.rb +20 -0
- data/lib/farce/internal/mutable_ordered_key_lock_map.rb +63 -0
- data/lib/farce/internal/noncopyable.rb +17 -0
- data/lib/farce/internal/ordered_key_lock_map.rb +69 -0
- data/lib/farce/internal/pool_supervisor.rb +41 -0
- data/lib/farce/internal/pool_worker.rb +61 -0
- data/lib/farce/internal/portable_transaction/reservation_entry.rb +29 -0
- data/lib/farce/internal/portable_transaction/strong_map_entry.rb +137 -0
- data/lib/farce/internal/portable_transaction/strong_map_size_entry.rb +44 -0
- data/lib/farce/internal/portable_transaction/tree_entry.rb +64 -0
- data/lib/farce/internal/portable_transaction.rb +164 -0
- data/lib/farce/internal/proxy_owner_notifications.rb +29 -0
- data/lib/farce/internal/reservation_waiting.rb +24 -0
- data/lib/farce/internal/scheduled_task.rb +48 -0
- data/lib/farce/internal/scheduler_io.rb +171 -0
- data/lib/farce/internal/scheduler_lifecycle.rb +314 -0
- data/lib/farce/internal/select_scheduler.rb +235 -0
- data/lib/farce/internal/storage.rb +162 -0
- data/lib/farce/internal/strict_lease.rb +30 -0
- data/lib/farce/internal/strict_lease_map.rb +20 -0
- data/lib/farce/internal/strict_lease_pool.rb +29 -0
- data/lib/farce/internal/thread_pool.rb +166 -0
- data/lib/farce/internal/transaction_conflict.rb +9 -0
- data/lib/farce/internal/transaction_freeze_guard.rb +30 -0
- data/lib/farce/internal/transaction_map_snapshot.rb +123 -0
- data/lib/farce/internal/undefined.rb +22 -0
- data/lib/farce/internal/unshared_lease.rb +29 -0
- data/lib/farce/internal/unshared_lease_pool.rb +34 -0
- data/lib/farce/internal/unshared_queue_waiting.rb +28 -0
- data/lib/farce/internal/value_serialization.rb +13 -0
- data/lib/farce/internal/weak_map_value_modes.rb +58 -0
- data/lib/farce/internal/weak_mode_manager.rb +26 -0
- data/lib/farce/internal.rb +129 -0
- data/lib/farce/lazy.rb +100 -0
- data/lib/farce/lazy_ref.rb +40 -0
- data/lib/farce/lease.rb +28 -0
- data/lib/farce/lease_map.rb +34 -0
- data/lib/farce/lease_pool.rb +29 -0
- data/lib/farce/lfu_map.rb +53 -0
- data/lib/farce/local/atom.rb +23 -0
- data/lib/farce/local/counter.rb +88 -0
- data/lib/farce/local/flag.rb +65 -0
- data/lib/farce/local/lazy.rb +38 -0
- data/lib/farce/local/lazy_ref.rb +36 -0
- data/lib/farce/local/lease.rb +77 -0
- data/lib/farce/local/lease_map.rb +80 -0
- data/lib/farce/local/lease_pool.rb +38 -0
- data/lib/farce/local/lfu_map.rb +55 -0
- data/lib/farce/local/lru_map.rb +62 -0
- data/lib/farce/local/map.rb +47 -0
- data/lib/farce/local/molecule.rb +45 -0
- data/lib/farce/local/priority_queue.rb +53 -0
- data/lib/farce/local/queue.rb +32 -0
- data/lib/farce/local/scoped.rb +166 -0
- data/lib/farce/local/set.rb +18 -0
- data/lib/farce/local/sorted_set.rb +50 -0
- data/lib/farce/local/timer_queue.rb +41 -0
- data/lib/farce/local/tree_map.rb +47 -0
- data/lib/farce/local/vector.rb +30 -0
- data/lib/farce/local/weak_atom.rb +23 -0
- data/lib/farce/local/weak_key_map.rb +39 -0
- data/lib/farce/local/weak_map.rb +39 -0
- data/lib/farce/local/weak_set.rb +18 -0
- data/lib/farce/local/weak_value_map.rb +39 -0
- data/lib/farce/local.rb +35 -0
- data/lib/farce/lock.rb +54 -0
- data/lib/farce/lru_map.rb +63 -0
- data/lib/farce/map.rb +58 -0
- data/lib/farce/mode_manager.rb +142 -0
- data/lib/farce/molecule.rb +60 -0
- data/lib/farce/mutable.rb +171 -0
- data/lib/farce/pool.rb +332 -0
- data/lib/farce/port.rb +134 -0
- data/lib/farce/priority_queue.rb +70 -0
- data/lib/farce/proxy/register.rb +101 -0
- data/lib/farce/proxy/supervisor.rb +137 -0
- data/lib/farce/proxy/wrapper.rb +49 -0
- data/lib/farce/proxy.rb +291 -0
- data/lib/farce/queue.rb +60 -0
- data/lib/farce/ractor.rb +269 -0
- data/lib/farce/read_write_lock.rb +256 -0
- data/lib/farce/reference.rb +158 -0
- data/lib/farce/resolv/dns.rb +42 -0
- data/lib/farce/resolv.rb +85 -0
- data/lib/farce/scheduler.rb +536 -0
- data/lib/farce/set.rb +39 -0
- data/lib/farce/shareable.rb +150 -0
- data/lib/farce/signal.rb +97 -0
- data/lib/farce/sorted_set.rb +36 -0
- data/lib/farce/strict/atom.rb +34 -0
- data/lib/farce/strict/counter.rb +10 -0
- data/lib/farce/strict/exchanger.rb +25 -0
- data/lib/farce/strict/flag.rb +10 -0
- data/lib/farce/strict/lazy.rb +26 -0
- data/lib/farce/strict/lazy_ref.rb +26 -0
- data/lib/farce/strict/lease.rb +27 -0
- data/lib/farce/strict/lease_map.rb +33 -0
- data/lib/farce/strict/lease_pool.rb +28 -0
- data/lib/farce/strict/lfu_map.rb +27 -0
- data/lib/farce/strict/lru_map.rb +28 -0
- data/lib/farce/strict/map.rb +54 -0
- data/lib/farce/strict/molecule.rb +16 -0
- data/lib/farce/strict/port.rb +40 -0
- data/lib/farce/strict/priority_queue.rb +20 -0
- data/lib/farce/strict/queue.rb +17 -0
- data/lib/farce/strict/set.rb +14 -0
- data/lib/farce/strict/sorted_set.rb +19 -0
- data/lib/farce/strict/timer_queue.rb +13 -0
- data/lib/farce/strict/tree_map.rb +27 -0
- data/lib/farce/strict/vector.rb +24 -0
- data/lib/farce/strict/weak_atom.rb +31 -0
- data/lib/farce/strict/weak_key_map.rb +49 -0
- data/lib/farce/strict/weak_map.rb +49 -0
- data/lib/farce/strict/weak_set.rb +14 -0
- data/lib/farce/strict/weak_value_map.rb +48 -0
- data/lib/farce/strict.rb +28 -0
- data/lib/farce/system.rb +40 -0
- data/lib/farce/thread_scheduler.rb +70 -0
- data/lib/farce/timer_queue.rb +66 -0
- data/lib/farce/transaction/atom.rb +73 -0
- data/lib/farce/transaction/map.rb +25 -0
- data/lib/farce/transaction/map_operations.rb +143 -0
- data/lib/farce/transaction/molecule.rb +90 -0
- data/lib/farce/transaction/mutable.rb +61 -0
- data/lib/farce/transaction/set.rb +17 -0
- data/lib/farce/transaction/set_operations.rb +48 -0
- data/lib/farce/transaction/sorted_set.rb +18 -0
- data/lib/farce/transaction/tree_map.rb +78 -0
- data/lib/farce/transaction/vector.rb +139 -0
- data/lib/farce/transaction/wrapper.rb +202 -0
- data/lib/farce/transaction.rb +343 -0
- data/lib/farce/tree_map.rb +56 -0
- data/lib/farce/unsafe/lfu_map.rb +36 -0
- data/lib/farce/unsafe/lru_map.rb +36 -0
- data/lib/farce/unsafe/tree_map.rb +21 -0
- data/lib/farce/unsafe.rb +29 -0
- data/lib/farce/unshareable.rb +67 -0
- data/lib/farce/unshared/atom.rb +24 -0
- data/lib/farce/unshared/counter.rb +10 -0
- data/lib/farce/unshared/flag.rb +10 -0
- data/lib/farce/unshared/lazy.rb +38 -0
- data/lib/farce/unshared/lazy_ref.rb +26 -0
- data/lib/farce/unshared/lease.rb +27 -0
- data/lib/farce/unshared/lease_map.rb +26 -0
- data/lib/farce/unshared/lease_pool.rb +25 -0
- data/lib/farce/unshared/lfu_map.rb +20 -0
- data/lib/farce/unshared/lru_map.rb +20 -0
- data/lib/farce/unshared/map.rb +49 -0
- data/lib/farce/unshared/molecule.rb +16 -0
- data/lib/farce/unshared/priority_queue.rb +16 -0
- data/lib/farce/unshared/queue.rb +27 -0
- data/lib/farce/unshared/set.rb +14 -0
- data/lib/farce/unshared/sorted_set.rb +28 -0
- data/lib/farce/unshared/timer_queue.rb +16 -0
- data/lib/farce/unshared/tree_map.rb +21 -0
- data/lib/farce/unshared/vector.rb +19 -0
- data/lib/farce/unshared/weak_atom.rb +31 -0
- data/lib/farce/unshared/weak_key_map.rb +44 -0
- data/lib/farce/unshared/weak_map.rb +44 -0
- data/lib/farce/unshared/weak_set.rb +14 -0
- data/lib/farce/unshared/weak_value_map.rb +43 -0
- data/lib/farce/unshared.rb +28 -0
- data/lib/farce/vector.rb +228 -0
- data/lib/farce/version.rb +8 -0
- data/lib/farce/walker/definitions.rb +186 -0
- data/lib/farce/walker/modification.rb +355 -0
- data/lib/farce/walker.rb +319 -0
- data/lib/farce/weak_atom.rb +121 -0
- data/lib/farce/weak_key_map.rb +31 -0
- data/lib/farce/weak_map.rb +33 -0
- data/lib/farce/weak_ref.rb +67 -0
- data/lib/farce/weak_set.rb +82 -0
- data/lib/farce/weak_value.rb +195 -0
- data/lib/farce/weak_value_map.rb +32 -0
- data/lib/farce.rb +519 -0
- metadata +435 -8
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#ifndef RACTOR_CONTAINERS_H
|
|
2
|
+
#define RACTOR_CONTAINERS_H
|
|
3
|
+
|
|
4
|
+
#include "ruby.h"
|
|
5
|
+
#include "ruby/ractor.h"
|
|
6
|
+
#include "ruby/thread.h"
|
|
7
|
+
|
|
8
|
+
#include <pthread.h>
|
|
9
|
+
#include <stdbool.h>
|
|
10
|
+
#include <stdint.h>
|
|
11
|
+
#ifndef _WIN32
|
|
12
|
+
#include <sys/time.h>
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
/* Use only after validating self as native TypedData. */
|
|
16
|
+
static inline void
|
|
17
|
+
containers_check_typed_frozen(VALUE self)
|
|
18
|
+
{
|
|
19
|
+
if (RB_UNLIKELY(RB_OBJ_FROZEN_RAW(self))) rb_error_frozen_object(self);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void containers_check_shareable(VALUE value);
|
|
23
|
+
bool containers_strict_bool(VALUE value, const char *name);
|
|
24
|
+
typedef void (*containers_native_reference_validator_t)(VALUE object);
|
|
25
|
+
VALUE containers_publish_native_reference_free(VALUE self);
|
|
26
|
+
VALUE containers_publish_native_with_references(
|
|
27
|
+
VALUE self,
|
|
28
|
+
containers_native_reference_validator_t validate_references
|
|
29
|
+
);
|
|
30
|
+
RBIMPL_ATTR_NORETURN()
|
|
31
|
+
VALUE containers_raise_unfreezable(VALUE self);
|
|
32
|
+
VALUE containers_normalize_string_key(VALUE key);
|
|
33
|
+
bool containers_wait_for_readable(int fd, VALUE timeout);
|
|
34
|
+
void containers_wait_without_descriptor(
|
|
35
|
+
int error, const char *operation, bool *collected, VALUE timeout
|
|
36
|
+
);
|
|
37
|
+
#ifdef _WIN32
|
|
38
|
+
void containers_wait_safepoint(void);
|
|
39
|
+
#endif
|
|
40
|
+
RBIMPL_ATTR_NORETURN()
|
|
41
|
+
void containers_raise_key_error(VALUE receiver, VALUE key);
|
|
42
|
+
|
|
43
|
+
void containers_init_atom(VALUE namespace);
|
|
44
|
+
void containers_init_counter(VALUE namespace);
|
|
45
|
+
void containers_init_exchanger(VALUE namespace);
|
|
46
|
+
void containers_init_flag(VALUE namespace);
|
|
47
|
+
void containers_init_lock(VALUE namespace);
|
|
48
|
+
typedef VALUE (*containers_lock_operation_t)(VALUE opaque);
|
|
49
|
+
VALUE containers_lock_new(void);
|
|
50
|
+
VALUE containers_lock_synchronize_call(
|
|
51
|
+
VALUE lock,
|
|
52
|
+
containers_lock_operation_t operation,
|
|
53
|
+
VALUE opaque
|
|
54
|
+
);
|
|
55
|
+
void containers_init_lru_maps(VALUE namespace);
|
|
56
|
+
void containers_init_map(VALUE namespace);
|
|
57
|
+
void containers_init_priority_queue(VALUE namespace);
|
|
58
|
+
void containers_init_darwin(VALUE namespace);
|
|
59
|
+
void containers_init_queue(VALUE namespace);
|
|
60
|
+
void containers_init_signal(VALUE namespace);
|
|
61
|
+
VALUE containers_signal_new(void);
|
|
62
|
+
VALUE containers_signal_broadcast(VALUE self);
|
|
63
|
+
|
|
64
|
+
typedef struct containers_unshared_signal containers_unshared_signal_t;
|
|
65
|
+
containers_unshared_signal_t *containers_unshared_signal_get_if_exact(VALUE signal);
|
|
66
|
+
bool containers_unshared_fiber_io(VALUE mode);
|
|
67
|
+
bool containers_unshared_signal_uses_fiber_io(VALUE signal);
|
|
68
|
+
bool containers_unshared_signal_has_waiters(containers_unshared_signal_t *signal);
|
|
69
|
+
void containers_unshared_signal_notify(containers_unshared_signal_t *signal);
|
|
70
|
+
void containers_init_unshared_signal(VALUE namespace);
|
|
71
|
+
void containers_init_unshareable(VALUE namespace);
|
|
72
|
+
void containers_init_vector(VALUE namespace);
|
|
73
|
+
void containers_init_weak_maps(VALUE namespace);
|
|
74
|
+
void containers_init_tree_maps(VALUE namespace);
|
|
75
|
+
void containers_init_trie(VALUE namespace);
|
|
76
|
+
|
|
77
|
+
#endif
|
data/ext/farce/counter.c
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
#include "containers.h"
|
|
2
|
+
|
|
3
|
+
#include <limits.h>
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
#include <stdatomic.h>
|
|
6
|
+
|
|
7
|
+
_Static_assert(sizeof(long long) == sizeof(int64_t), "Counter requires a 64-bit long long");
|
|
8
|
+
_Static_assert(LLONG_MIN == INT64_MIN, "Counter requires a signed 64-bit long long");
|
|
9
|
+
_Static_assert(LLONG_MAX == INT64_MAX, "Counter requires a signed 64-bit long long");
|
|
10
|
+
|
|
11
|
+
#if ATOMIC_LLONG_LOCK_FREE == 2
|
|
12
|
+
#define CONTAINERS_COUNTER_LOCK_FREE 1
|
|
13
|
+
#else
|
|
14
|
+
#define CONTAINERS_COUNTER_LOCK_FREE 0
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
static VALUE cCounter;
|
|
18
|
+
|
|
19
|
+
typedef struct {
|
|
20
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
21
|
+
_Atomic long long value;
|
|
22
|
+
#else
|
|
23
|
+
pthread_mutex_t lock;
|
|
24
|
+
long long value;
|
|
25
|
+
#endif
|
|
26
|
+
VALUE signal;
|
|
27
|
+
long long initial;
|
|
28
|
+
bool initialized;
|
|
29
|
+
} counter_t;
|
|
30
|
+
|
|
31
|
+
/* On platforms with always-lock-free 64-bit atomics, counter operations only
|
|
32
|
+
* linearize this numeric value. Relaxed ordering does not publish or
|
|
33
|
+
* synchronize accesses to any other shared state. Platforms without that
|
|
34
|
+
* guarantee use a mutex so 32-bit cross builds do not depend on libatomic. */
|
|
35
|
+
|
|
36
|
+
static void
|
|
37
|
+
counter_free(void *pointer)
|
|
38
|
+
{
|
|
39
|
+
#if !CONTAINERS_COUNTER_LOCK_FREE
|
|
40
|
+
counter_t *counter = pointer;
|
|
41
|
+
if (counter) pthread_mutex_destroy(&counter->lock);
|
|
42
|
+
#endif
|
|
43
|
+
ruby_xfree(pointer);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static size_t
|
|
47
|
+
counter_memsize(const void *pointer)
|
|
48
|
+
{
|
|
49
|
+
return pointer ? sizeof(counter_t) : 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static void
|
|
53
|
+
counter_mark(void *pointer)
|
|
54
|
+
{
|
|
55
|
+
counter_t *counter = pointer;
|
|
56
|
+
rb_gc_mark_movable(counter->signal);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static void
|
|
60
|
+
counter_compact(void *pointer)
|
|
61
|
+
{
|
|
62
|
+
counter_t *counter = pointer;
|
|
63
|
+
counter->signal = rb_gc_location(counter->signal);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static const rb_data_type_t counter_type = {
|
|
67
|
+
.wrap_struct_name = "Ractor::Containers::Counter",
|
|
68
|
+
.function = {
|
|
69
|
+
.dmark = counter_mark,
|
|
70
|
+
.dcompact = counter_compact,
|
|
71
|
+
.dfree = counter_free,
|
|
72
|
+
.dsize = counter_memsize,
|
|
73
|
+
},
|
|
74
|
+
.flags = RUBY_TYPED_FROZEN_SHAREABLE,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
static VALUE
|
|
78
|
+
counter_allocate(VALUE klass)
|
|
79
|
+
{
|
|
80
|
+
counter_t *counter;
|
|
81
|
+
VALUE object = TypedData_Make_Struct(klass, counter_t, &counter_type, counter);
|
|
82
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
83
|
+
atomic_init(&counter->value, 0);
|
|
84
|
+
#else
|
|
85
|
+
pthread_mutex_init(&counter->lock, NULL);
|
|
86
|
+
counter->value = 0;
|
|
87
|
+
#endif
|
|
88
|
+
counter->signal = Qnil;
|
|
89
|
+
counter->initialized = false;
|
|
90
|
+
return object;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static counter_t *
|
|
94
|
+
get_counter(VALUE self)
|
|
95
|
+
{
|
|
96
|
+
counter_t *counter;
|
|
97
|
+
TypedData_Get_Struct(self, counter_t, &counter_type, counter);
|
|
98
|
+
if (!counter->initialized) rb_raise(rb_eRuntimeError, "uninitialized Counter");
|
|
99
|
+
return counter;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static void
|
|
103
|
+
counter_validate_references(VALUE self)
|
|
104
|
+
{
|
|
105
|
+
containers_check_shareable(get_counter(self)->signal);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static VALUE
|
|
109
|
+
counter_change_signal(VALUE self)
|
|
110
|
+
{
|
|
111
|
+
return get_counter(self)->signal;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static long long
|
|
115
|
+
counter_integer(VALUE value, const char *name)
|
|
116
|
+
{
|
|
117
|
+
if (!RB_INTEGER_TYPE_P(value)) rb_raise(rb_eTypeError, "%s must be an Integer", name);
|
|
118
|
+
return NUM2LL(value);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static VALUE
|
|
122
|
+
counter_initialize(int argc, VALUE *argv, VALUE self)
|
|
123
|
+
{
|
|
124
|
+
counter_t *counter;
|
|
125
|
+
|
|
126
|
+
rb_check_arity(argc, 0, 1);
|
|
127
|
+
VALUE initial = argc == 0 ? INT2FIX(0) : argv[0];
|
|
128
|
+
TypedData_Get_Struct(self, counter_t, &counter_type, counter);
|
|
129
|
+
if (counter->initialized) rb_raise(rb_eRuntimeError, "Counter is already initialized");
|
|
130
|
+
rb_check_frozen(self);
|
|
131
|
+
|
|
132
|
+
long long value = counter_integer(initial, "initial value");
|
|
133
|
+
rb_check_frozen(self);
|
|
134
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
135
|
+
atomic_store_explicit(&counter->value, value, memory_order_relaxed);
|
|
136
|
+
#else
|
|
137
|
+
counter->value = value;
|
|
138
|
+
#endif
|
|
139
|
+
counter->signal = containers_signal_new();
|
|
140
|
+
counter->initial = value;
|
|
141
|
+
counter->initialized = true;
|
|
142
|
+
return containers_publish_native_with_references(self, counter_validate_references);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static VALUE
|
|
146
|
+
counter_value(VALUE self)
|
|
147
|
+
{
|
|
148
|
+
counter_t *counter = get_counter(self);
|
|
149
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
150
|
+
long long value = atomic_load_explicit(&counter->value, memory_order_relaxed);
|
|
151
|
+
#else
|
|
152
|
+
pthread_mutex_lock(&counter->lock);
|
|
153
|
+
long long value = counter->value;
|
|
154
|
+
pthread_mutex_unlock(&counter->lock);
|
|
155
|
+
#endif
|
|
156
|
+
return LL2NUM(value);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static VALUE
|
|
160
|
+
counter_initial(VALUE self)
|
|
161
|
+
{
|
|
162
|
+
return LL2NUM(get_counter(self)->initial);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static VALUE
|
|
166
|
+
counter_initialize_copy(VALUE self, VALUE other)
|
|
167
|
+
{
|
|
168
|
+
if (self == other) return self;
|
|
169
|
+
rb_check_frozen(self);
|
|
170
|
+
counter_t *copy;
|
|
171
|
+
TypedData_Get_Struct(self, counter_t, &counter_type, copy);
|
|
172
|
+
if (copy->initialized) rb_raise(rb_eRuntimeError, "copy is already initialized");
|
|
173
|
+
counter_t *source = get_counter(other);
|
|
174
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
175
|
+
long long value = atomic_load_explicit(&source->value, memory_order_relaxed);
|
|
176
|
+
#else
|
|
177
|
+
pthread_mutex_lock(&source->lock);
|
|
178
|
+
long long value = source->value;
|
|
179
|
+
pthread_mutex_unlock(&source->lock);
|
|
180
|
+
#endif
|
|
181
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
182
|
+
atomic_store_explicit(©->value, value, memory_order_relaxed);
|
|
183
|
+
#else
|
|
184
|
+
copy->value = value;
|
|
185
|
+
#endif
|
|
186
|
+
copy->signal = containers_signal_new();
|
|
187
|
+
copy->initial = source->initial;
|
|
188
|
+
copy->initialized = true;
|
|
189
|
+
return containers_publish_native_with_references(self, counter_validate_references);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
static VALUE
|
|
193
|
+
counter_store(VALUE self, VALUE input)
|
|
194
|
+
{
|
|
195
|
+
counter_t *counter = get_counter(self);
|
|
196
|
+
rb_check_frozen(self);
|
|
197
|
+
long long value = counter_integer(input, "value");
|
|
198
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
199
|
+
atomic_store_explicit(&counter->value, value, memory_order_relaxed);
|
|
200
|
+
#else
|
|
201
|
+
pthread_mutex_lock(&counter->lock);
|
|
202
|
+
counter->value = value;
|
|
203
|
+
pthread_mutex_unlock(&counter->lock);
|
|
204
|
+
#endif
|
|
205
|
+
containers_signal_broadcast(counter->signal);
|
|
206
|
+
return input;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
static VALUE
|
|
210
|
+
counter_swap(VALUE self, VALUE input)
|
|
211
|
+
{
|
|
212
|
+
counter_t *counter = get_counter(self);
|
|
213
|
+
rb_check_frozen(self);
|
|
214
|
+
long long replacement = counter_integer(input, "value");
|
|
215
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
216
|
+
long long current = atomic_load_explicit(&counter->value, memory_order_relaxed);
|
|
217
|
+
|
|
218
|
+
for (;;) {
|
|
219
|
+
VALUE result = LL2NUM(current);
|
|
220
|
+
if (atomic_compare_exchange_weak_explicit(
|
|
221
|
+
&counter->value,
|
|
222
|
+
¤t,
|
|
223
|
+
replacement,
|
|
224
|
+
memory_order_relaxed,
|
|
225
|
+
memory_order_relaxed
|
|
226
|
+
)) {
|
|
227
|
+
containers_signal_broadcast(counter->signal);
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
#else
|
|
232
|
+
pthread_mutex_lock(&counter->lock);
|
|
233
|
+
long long current = counter->value;
|
|
234
|
+
counter->value = replacement;
|
|
235
|
+
pthread_mutex_unlock(&counter->lock);
|
|
236
|
+
containers_signal_broadcast(counter->signal);
|
|
237
|
+
return LL2NUM(current);
|
|
238
|
+
#endif
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
static bool
|
|
242
|
+
counter_add_overflows(long long current, long long delta)
|
|
243
|
+
{
|
|
244
|
+
return (delta > 0 && current > LLONG_MAX - delta) ||
|
|
245
|
+
(delta < 0 && current < LLONG_MIN - delta);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
static bool
|
|
249
|
+
counter_subtract_overflows(long long current, long long delta)
|
|
250
|
+
{
|
|
251
|
+
return (delta > 0 && current < LLONG_MIN + delta) ||
|
|
252
|
+
(delta < 0 && current > LLONG_MAX + delta);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
static VALUE
|
|
256
|
+
counter_change(counter_t *counter, long long delta, bool subtract)
|
|
257
|
+
{
|
|
258
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
259
|
+
long long current = atomic_load_explicit(&counter->value, memory_order_relaxed);
|
|
260
|
+
|
|
261
|
+
for (;;) {
|
|
262
|
+
bool overflows = subtract
|
|
263
|
+
? counter_subtract_overflows(current, delta)
|
|
264
|
+
: counter_add_overflows(current, delta);
|
|
265
|
+
if (overflows) rb_raise(rb_eRangeError, "counter value is outside the signed 64-bit range");
|
|
266
|
+
|
|
267
|
+
long long replacement = subtract ? current - delta : current + delta;
|
|
268
|
+
VALUE result = LL2NUM(replacement);
|
|
269
|
+
if (atomic_compare_exchange_weak_explicit(
|
|
270
|
+
&counter->value,
|
|
271
|
+
¤t,
|
|
272
|
+
replacement,
|
|
273
|
+
memory_order_relaxed,
|
|
274
|
+
memory_order_relaxed
|
|
275
|
+
)) {
|
|
276
|
+
containers_signal_broadcast(counter->signal);
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
#else
|
|
281
|
+
pthread_mutex_lock(&counter->lock);
|
|
282
|
+
long long current = counter->value;
|
|
283
|
+
bool overflows = subtract
|
|
284
|
+
? counter_subtract_overflows(current, delta)
|
|
285
|
+
: counter_add_overflows(current, delta);
|
|
286
|
+
if (overflows) {
|
|
287
|
+
pthread_mutex_unlock(&counter->lock);
|
|
288
|
+
rb_raise(rb_eRangeError, "counter value is outside the signed 64-bit range");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
long long replacement = subtract ? current - delta : current + delta;
|
|
292
|
+
counter->value = replacement;
|
|
293
|
+
pthread_mutex_unlock(&counter->lock);
|
|
294
|
+
containers_signal_broadcast(counter->signal);
|
|
295
|
+
return LL2NUM(replacement);
|
|
296
|
+
#endif
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
static VALUE
|
|
300
|
+
counter_add(int argc, VALUE *argv, VALUE self)
|
|
301
|
+
{
|
|
302
|
+
rb_check_arity(argc, 0, 1);
|
|
303
|
+
counter_t *counter = get_counter(self);
|
|
304
|
+
rb_check_frozen(self);
|
|
305
|
+
VALUE input = argc == 0 ? INT2FIX(1) : argv[0];
|
|
306
|
+
long long delta = counter_integer(input, "delta");
|
|
307
|
+
return counter_change(counter, delta, false);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
static VALUE
|
|
311
|
+
counter_subtract(int argc, VALUE *argv, VALUE self)
|
|
312
|
+
{
|
|
313
|
+
rb_check_arity(argc, 0, 1);
|
|
314
|
+
counter_t *counter = get_counter(self);
|
|
315
|
+
rb_check_frozen(self);
|
|
316
|
+
VALUE input = argc == 0 ? INT2FIX(1) : argv[0];
|
|
317
|
+
long long delta = counter_integer(input, "delta");
|
|
318
|
+
return counter_change(counter, delta, true);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
static VALUE
|
|
322
|
+
counter_compare_and_set(VALUE self, VALUE expected_input, VALUE replacement_input)
|
|
323
|
+
{
|
|
324
|
+
counter_t *counter = get_counter(self);
|
|
325
|
+
rb_check_frozen(self);
|
|
326
|
+
long long expected = counter_integer(expected_input, "expected value");
|
|
327
|
+
long long replacement = counter_integer(replacement_input, "replacement value");
|
|
328
|
+
#if CONTAINERS_COUNTER_LOCK_FREE
|
|
329
|
+
bool exchanged = atomic_compare_exchange_strong_explicit(
|
|
330
|
+
&counter->value,
|
|
331
|
+
&expected,
|
|
332
|
+
replacement,
|
|
333
|
+
memory_order_relaxed,
|
|
334
|
+
memory_order_relaxed
|
|
335
|
+
);
|
|
336
|
+
#else
|
|
337
|
+
pthread_mutex_lock(&counter->lock);
|
|
338
|
+
bool exchanged = counter->value == expected;
|
|
339
|
+
if (exchanged) counter->value = replacement;
|
|
340
|
+
pthread_mutex_unlock(&counter->lock);
|
|
341
|
+
#endif
|
|
342
|
+
if (exchanged) containers_signal_broadcast(counter->signal);
|
|
343
|
+
return exchanged ? Qtrue : Qfalse;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* The chainable operations are inherited directly by Farce::Counter. Keep
|
|
347
|
+
* add/subtract as strict, value-returning primitives for internal callers. */
|
|
348
|
+
static VALUE
|
|
349
|
+
counter_increment(int argc, VALUE *argv, VALUE self)
|
|
350
|
+
{
|
|
351
|
+
rb_check_arity(argc, 0, 1);
|
|
352
|
+
counter_t *counter = get_counter(self);
|
|
353
|
+
rb_check_frozen(self);
|
|
354
|
+
VALUE input = argc == 0 ? INT2FIX(1) : argv[0];
|
|
355
|
+
if (!RB_INTEGER_TYPE_P(input)) {
|
|
356
|
+
input = rb_Integer(input);
|
|
357
|
+
rb_check_frozen(self);
|
|
358
|
+
}
|
|
359
|
+
long long delta = NUM2LL(input);
|
|
360
|
+
(void)counter_change(counter, delta, false);
|
|
361
|
+
return self;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
static VALUE
|
|
365
|
+
counter_decrement(int argc, VALUE *argv, VALUE self)
|
|
366
|
+
{
|
|
367
|
+
rb_check_arity(argc, 0, 1);
|
|
368
|
+
counter_t *counter = get_counter(self);
|
|
369
|
+
rb_check_frozen(self);
|
|
370
|
+
VALUE input = argc == 0 ? INT2FIX(1) : argv[0];
|
|
371
|
+
if (!RB_INTEGER_TYPE_P(input)) {
|
|
372
|
+
input = rb_Integer(input);
|
|
373
|
+
rb_check_frozen(self);
|
|
374
|
+
}
|
|
375
|
+
long long delta = NUM2LL(input);
|
|
376
|
+
(void)counter_change(counter, delta, true);
|
|
377
|
+
return self;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
void
|
|
381
|
+
containers_init_counter(VALUE namespace)
|
|
382
|
+
{
|
|
383
|
+
cCounter = rb_define_class_under(namespace, "Counter", rb_cNumeric);
|
|
384
|
+
rb_define_alloc_func(cCounter, counter_allocate);
|
|
385
|
+
rb_define_method(cCounter, "initialize", counter_initialize, -1);
|
|
386
|
+
rb_define_private_method(cCounter, "initialize_copy", counter_initialize_copy, 1);
|
|
387
|
+
rb_define_method(cCounter, "value", counter_value, 0);
|
|
388
|
+
rb_define_alias(cCounter, "get", "value");
|
|
389
|
+
rb_define_method(cCounter, "change_signal", counter_change_signal, 0);
|
|
390
|
+
rb_define_method(cCounter, "initial", counter_initial, 0);
|
|
391
|
+
rb_define_method(cCounter, "store", counter_store, 1);
|
|
392
|
+
rb_define_alias(cCounter, "value=", "store");
|
|
393
|
+
rb_define_method(cCounter, "swap", counter_swap, 1);
|
|
394
|
+
rb_define_method(cCounter, "add", counter_add, -1);
|
|
395
|
+
rb_define_method(cCounter, "increment", counter_increment, -1);
|
|
396
|
+
rb_define_method(cCounter, "subtract", counter_subtract, -1);
|
|
397
|
+
rb_define_method(cCounter, "decrement", counter_decrement, -1);
|
|
398
|
+
rb_define_method(cCounter, "compare_and_set", counter_compare_and_set, 2);
|
|
399
|
+
}
|
data/ext/farce/darwin.c
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#include "containers.h"
|
|
2
|
+
|
|
3
|
+
#if defined(HAVE_PTHREAD_QOS_H) && \
|
|
4
|
+
defined(HAVE_PTHREAD_SET_QOS_CLASS_SELF_NP) && \
|
|
5
|
+
defined(HAVE_PTHREAD_GET_QOS_CLASS_NP)
|
|
6
|
+
#include <pthread/qos.h>
|
|
7
|
+
#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)
|
|
8
|
+
#include <errno.h>
|
|
9
|
+
#include <sys/sysctl.h>
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
static VALUE
|
|
13
|
+
darwin_set_qos_class(VALUE self, VALUE qos_class, VALUE relative_priority)
|
|
14
|
+
{
|
|
15
|
+
int error = pthread_set_qos_class_self_np(
|
|
16
|
+
(qos_class_t)NUM2UINT(qos_class),
|
|
17
|
+
NUM2INT(relative_priority)
|
|
18
|
+
);
|
|
19
|
+
if (error) rb_syserr_fail(error, "pthread_set_qos_class_self_np");
|
|
20
|
+
return Qnil;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static VALUE
|
|
24
|
+
darwin_get_qos_class(VALUE self)
|
|
25
|
+
{
|
|
26
|
+
qos_class_t qos_class;
|
|
27
|
+
int relative_priority;
|
|
28
|
+
int error = pthread_get_qos_class_np(pthread_self(), &qos_class, &relative_priority);
|
|
29
|
+
if (error) rb_syserr_fail(error, "pthread_get_qos_class_np");
|
|
30
|
+
return rb_assoc_new(UINT2NUM(qos_class), INT2NUM(relative_priority));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
#ifdef HAVE_QOS_CLASS_MAIN
|
|
34
|
+
static VALUE
|
|
35
|
+
darwin_main_qos_class(VALUE self)
|
|
36
|
+
{
|
|
37
|
+
return UINT2NUM(qos_class_main());
|
|
38
|
+
}
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)
|
|
42
|
+
static VALUE
|
|
43
|
+
darwin_read_cpu_count(const char *name, bool optional)
|
|
44
|
+
{
|
|
45
|
+
int count;
|
|
46
|
+
size_t size = sizeof(count);
|
|
47
|
+
if (sysctlbyname(name, &count, &size, NULL, 0) == -1) {
|
|
48
|
+
if (optional && errno == ENOENT) return Qnil;
|
|
49
|
+
rb_sys_fail(name);
|
|
50
|
+
}
|
|
51
|
+
return INT2NUM(count);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static VALUE
|
|
55
|
+
darwin_performance_cpu_count(VALUE self)
|
|
56
|
+
{
|
|
57
|
+
return darwin_read_cpu_count("hw.perflevel0.logicalcpu", true);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static VALUE
|
|
61
|
+
darwin_efficiency_cpu_count(VALUE self)
|
|
62
|
+
{
|
|
63
|
+
return darwin_read_cpu_count("hw.perflevel1.logicalcpu", true);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static VALUE
|
|
67
|
+
darwin_cpu_count(VALUE self)
|
|
68
|
+
{
|
|
69
|
+
return darwin_read_cpu_count("hw.logicalcpu", false);
|
|
70
|
+
}
|
|
71
|
+
#endif
|
|
72
|
+
#endif
|
|
73
|
+
|
|
74
|
+
void
|
|
75
|
+
containers_init_darwin(VALUE namespace)
|
|
76
|
+
{
|
|
77
|
+
#if defined(HAVE_PTHREAD_QOS_H) && \
|
|
78
|
+
defined(HAVE_PTHREAD_SET_QOS_CLASS_SELF_NP) && \
|
|
79
|
+
defined(HAVE_PTHREAD_GET_QOS_CLASS_NP)
|
|
80
|
+
VALUE darwin = rb_define_module_under(namespace, "Darwin");
|
|
81
|
+
rb_define_singleton_method(darwin, "set_qos_class", darwin_set_qos_class, 2);
|
|
82
|
+
rb_define_singleton_method(darwin, "get_qos_class", darwin_get_qos_class, 0);
|
|
83
|
+
#ifdef HAVE_QOS_CLASS_MAIN
|
|
84
|
+
rb_define_singleton_method(darwin, "main_qos_class", darwin_main_qos_class, 0);
|
|
85
|
+
#endif
|
|
86
|
+
#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)
|
|
87
|
+
rb_define_singleton_method(darwin, "performance_cpu_count", darwin_performance_cpu_count, 0);
|
|
88
|
+
rb_define_singleton_method(darwin, "efficiency_cpu_count", darwin_efficiency_cpu_count, 0);
|
|
89
|
+
rb_define_singleton_method(darwin, "cpu_count", darwin_cpu_count, 0);
|
|
90
|
+
#endif
|
|
91
|
+
|
|
92
|
+
rb_define_const(darwin, "MIN_RELATIVE_PRIORITY", INT2NUM(QOS_MIN_RELATIVE_PRIORITY));
|
|
93
|
+
rb_define_const(darwin, "USER_INTERACTIVE", UINT2NUM(QOS_CLASS_USER_INTERACTIVE));
|
|
94
|
+
rb_define_const(darwin, "USER_INITIATED", UINT2NUM(QOS_CLASS_USER_INITIATED));
|
|
95
|
+
rb_define_const(darwin, "DEFAULT", UINT2NUM(QOS_CLASS_DEFAULT));
|
|
96
|
+
rb_define_const(darwin, "UTILITY", UINT2NUM(QOS_CLASS_UTILITY));
|
|
97
|
+
rb_define_const(darwin, "BACKGROUND", UINT2NUM(QOS_CLASS_BACKGROUND));
|
|
98
|
+
rb_define_const(darwin, "UNSPECIFIED", UINT2NUM(QOS_CLASS_UNSPECIFIED));
|
|
99
|
+
#endif
|
|
100
|
+
}
|
data/ext/farce/depend
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
bounded_map.o: bounded_map.c containers.h
|
|
2
|
+
dict.o: dict.c dict.h
|
|
3
|
+
farce.o: farce.c containers.h shareable.h
|
|
4
|
+
lock.o: lock.c containers.h
|
|
5
|
+
priority_queue.o: priority_queue.c containers.h dict.h unshared_wait.h
|
|
6
|
+
reactor.o: reactor.c reactor.h
|
|
7
|
+
drivers.o: drivers.c reactor.h
|
|
8
|
+
io.o: io.c reactor.h
|
|
9
|
+
tree_map.o: tree_map.c containers.h
|
|
10
|
+
|
|
11
|
+
queue.o: queue.c containers.h unshared_wait.h
|
|
12
|
+
unshared_signal.o: unshared_signal.c containers.h unshared_wait.h unshared_io_pool.h
|