farce 0.3.0 → 0.4.1
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 +50 -0
- data/README.md +117 -1489
- data/docs/compatibility.md +74 -0
- data/docs/concurrency.md +151 -0
- data/docs/data-structures.md +313 -0
- data/docs/installation.md +63 -0
- data/docs/integrations.md +124 -0
- data/docs/introduction.md +266 -0
- data/docs/scheduling.md +176 -0
- data/docs/sharing.md +211 -0
- data/docs/shims.md +144 -0
- data/docs/utilities.md +93 -0
- data/docs/variants-and-scopes.md +92 -0
- data/ext/farce/LIBURING-LICENSE +20 -0
- data/ext/farce/atom.c +23 -66
- data/ext/farce/counter.c +1 -1
- data/ext/farce/depend +15 -7
- data/ext/farce/drivers.c +44 -2
- data/ext/farce/exchanger.c +1 -1
- data/ext/farce/extconf.rb +45 -2
- data/ext/farce/farce.c +8 -0
- data/ext/farce/flag.c +1 -1
- data/ext/farce/futex.c +76 -0
- data/ext/farce/futex.h +31 -0
- data/ext/farce/lock.c +16 -62
- data/ext/farce/map.c +10 -54
- data/ext/farce/native_wait.c +139 -0
- data/ext/farce/native_wait.h +37 -0
- data/ext/farce/priority_queue.c +16 -58
- data/ext/farce/queue.c +1 -1
- data/ext/farce/reactor.c +100 -11
- data/ext/farce/reactor.h +6 -2
- data/ext/farce/signal.c +17 -64
- data/ext/farce/tree_map.c +15 -54
- data/ext/farce/unshareable.c +1 -1
- data/ext/farce/unsupported.c +13 -1
- data/ext/farce/vector.c +13 -60
- data/ext/farce/weak_map.c +1 -1
- data/lib/farce/abstract/flag.rb +6 -0
- data/lib/farce/backports.rb +274 -0
- data/lib/farce/engine/jruby/fiber_scheduler.rb +3 -0
- data/lib/farce/engine/jruby/scheduler_synchronization.rb +87 -0
- data/lib/farce/engine/ruby/3.4/null_port.rb +21 -0
- data/lib/farce/engine/ruby/3.4/patch.rb +67 -0
- data/lib/farce/engine/ruby/3.4/port.rb +13 -12
- data/lib/farce/engine/ruby/3.4/ractor_methods.rb +0 -1
- data/lib/farce/engine/ruby/4.0/null_port.rb +36 -0
- data/lib/farce/engine/ruby/4.0/port.rb +1 -2
- data/lib/farce/engine/ruby/4.1/null_port.rb +5 -0
- data/lib/farce/engine/ruby.rb +7 -0
- data/lib/farce/engine/shared/null_port.rb +18 -0
- data/lib/farce/engine/shared/port.rb +41 -3
- data/lib/farce/engine/shared/queue.rb +4 -4
- data/lib/farce/engine/shared/ractor_methods.rb +2 -2
- data/lib/farce/engine/shared/ractor_selector.rb +73 -0
- data/lib/farce/extension.rb +150 -0
- data/lib/farce/integrations/ractor_tmvar.rb +4 -1
- data/lib/farce/internal/fake_ractor.rb +10 -2
- data/lib/farce/internal/scheduler_lifecycle.rb +7 -4
- data/lib/farce/null_port.rb +12 -0
- data/lib/farce/system.rb +10 -2
- data/lib/farce/version.rb +1 -1
- data/lib/farce.rb +1 -1
- metadata +27 -1
|
@@ -10,11 +10,19 @@ module Farce
|
|
|
10
10
|
include MarshalSupport::Reject
|
|
11
11
|
include Freeze::Unfreezable
|
|
12
12
|
|
|
13
|
-
def initialize
|
|
14
|
-
|
|
13
|
+
def initialize
|
|
14
|
+
@queue = Thread::Queue.new
|
|
15
|
+
@select_mutex = Mutex.new
|
|
16
|
+
@select_waiters = []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def closed? = @queue.closed?
|
|
15
20
|
|
|
16
21
|
def close
|
|
17
|
-
@
|
|
22
|
+
@select_mutex.synchronize do
|
|
23
|
+
@queue.close
|
|
24
|
+
@select_waiters.each(&:broadcast)
|
|
25
|
+
end
|
|
18
26
|
self
|
|
19
27
|
end
|
|
20
28
|
|
|
@@ -29,14 +37,44 @@ module Farce
|
|
|
29
37
|
raise Ractor::Error, "can not move #{value.class} object" unless value.is_a?(Unshareable::Movable)
|
|
30
38
|
end
|
|
31
39
|
@queue.push(value)
|
|
40
|
+
notify_selectors
|
|
32
41
|
self
|
|
33
42
|
rescue ::ClosedQueueError
|
|
34
43
|
raise Ractor::ClosedError, "The port was already closed"
|
|
35
44
|
end
|
|
36
45
|
|
|
46
|
+
# @api private
|
|
47
|
+
def register_selector(waiter)
|
|
48
|
+
@select_mutex.synchronize { @select_waiters << waiter }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @api private
|
|
52
|
+
def unregister_selector(waiter)
|
|
53
|
+
@select_mutex.synchronize { @select_waiters.delete(waiter) }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @api private
|
|
57
|
+
def select_receive
|
|
58
|
+
@select_mutex.synchronize do
|
|
59
|
+
raise Ractor::ClosedError, "The port was already closed" if closed?
|
|
60
|
+
begin
|
|
61
|
+
value = @queue.pop(true)
|
|
62
|
+
rescue ThreadError
|
|
63
|
+
return
|
|
64
|
+
end
|
|
65
|
+
[self, value]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
37
69
|
alias << send
|
|
38
70
|
|
|
39
71
|
def inspect = "#<#{self.class.name} to:#1 id:#{object_id}>"
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def notify_selectors
|
|
76
|
+
@select_mutex.synchronize { @select_waiters.each(&:broadcast) }
|
|
77
|
+
end
|
|
40
78
|
end
|
|
41
79
|
|
|
42
80
|
BasePort = Port
|
|
@@ -12,10 +12,10 @@ module Farce
|
|
|
12
12
|
attr_reader :capacity
|
|
13
13
|
|
|
14
14
|
def initialize(capacity: 1024, track_age: false)
|
|
15
|
-
@queue
|
|
16
|
-
@capacity
|
|
17
|
-
@signal
|
|
18
|
-
@tracking
|
|
15
|
+
@queue = capacity ? Thread::SizedQueue.new(capacity) : Thread::Queue.new
|
|
16
|
+
@capacity = capacity
|
|
17
|
+
@signal = Signal.new
|
|
18
|
+
@tracking = track_age ? { lock: Mutex.new, timestamps: [], generation: 0 } : nil
|
|
19
19
|
@lifecycle = { lock: Mutex.new, hard_closed: false }
|
|
20
20
|
Freeze.publish(self)
|
|
21
21
|
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# @!visibility private
|
|
7
|
+
module Internal # :nodoc: all
|
|
8
|
+
# Wait for shim port readiness without consuming messages from losing ports.
|
|
9
|
+
class RactorSelector
|
|
10
|
+
def select(*sources, timeout: nil)
|
|
11
|
+
raise ArgumentError, "specify at least one Ractor::Port or Ractor" if sources.empty?
|
|
12
|
+
sources.each do |source|
|
|
13
|
+
next if source.is_a?(Ractor) || source.is_a?(Port)
|
|
14
|
+
raise ArgumentError, "should be Ractor::Port or Ractor"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
timeout = duration(timeout)
|
|
18
|
+
deadline = Clock.now + timeout if timeout
|
|
19
|
+
monitors = {}.compare_by_identity
|
|
20
|
+
ports = sources.uniq.map do |source|
|
|
21
|
+
next source unless source.is_a?(Ractor)
|
|
22
|
+
|
|
23
|
+
port = BasePort.new
|
|
24
|
+
monitors[port] = source
|
|
25
|
+
source.monitor(port)
|
|
26
|
+
port
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
result = wait(ports, deadline)
|
|
30
|
+
return unless result
|
|
31
|
+
|
|
32
|
+
port, value = result
|
|
33
|
+
ractor = monitors[port]
|
|
34
|
+
ractor ? [ractor, ractor.value] : [port, value]
|
|
35
|
+
ensure
|
|
36
|
+
monitors&.each do |port, ractor|
|
|
37
|
+
ractor.unmonitor(port)
|
|
38
|
+
port.close
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def duration(value)
|
|
45
|
+
return if value.nil?
|
|
46
|
+
raise TypeError, "cannot convert String into time interval" if value.is_a?(String)
|
|
47
|
+
value = Float(value)
|
|
48
|
+
raise RangeError, "timeout out of range" unless value.finite?
|
|
49
|
+
raise ArgumentError, "time interval must not be negative" if value.negative?
|
|
50
|
+
value
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def wait(ports, deadline)
|
|
54
|
+
wakeup = Signal.new
|
|
55
|
+
ports.each { it.register_selector(wakeup) }
|
|
56
|
+
while true
|
|
57
|
+
# Observe before checking readiness so a send during that check
|
|
58
|
+
# changes the generation and prevents the following wait from parking.
|
|
59
|
+
generation = wakeup.generation
|
|
60
|
+
ports.each do |port|
|
|
61
|
+
result = port.select_receive
|
|
62
|
+
return result if result
|
|
63
|
+
end
|
|
64
|
+
remaining = deadline - Clock.now if deadline
|
|
65
|
+
return if remaining && !remaining.positive?
|
|
66
|
+
return unless ReservationWaiting.wait(wakeup, generation, deadline)
|
|
67
|
+
end
|
|
68
|
+
ensure
|
|
69
|
+
ports.each { it.unregister_selector(wakeup) }
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# Defines a reusable extension for adding methods to target classes.
|
|
7
|
+
# These methods can either be activated as refinements, or installed globally to extend the target classes.
|
|
8
|
+
#
|
|
9
|
+
# ```ruby
|
|
10
|
+
# DoubleSize = Farce::Extension.define(String) do
|
|
11
|
+
# def double_size = size * 2
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# module Namespace
|
|
15
|
+
# using DoubleSize
|
|
16
|
+
# "hello".double_size # => 10
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# "hello".respond_to?(:double_size) # => false
|
|
20
|
+
#
|
|
21
|
+
# DoubleSize.install
|
|
22
|
+
# "hello".respond_to?(:double_size) # => true
|
|
23
|
+
# ```
|
|
24
|
+
#
|
|
25
|
+
# ## Extending multiple classes
|
|
26
|
+
#
|
|
27
|
+
# An extension can also modify multiple target classes simultaneously:
|
|
28
|
+
#
|
|
29
|
+
# ```ruby
|
|
30
|
+
# DoubleSize = Farce::Extension.new do
|
|
31
|
+
# define(String) { def double_size = size * 2 }
|
|
32
|
+
# define(Array) { def double_size = sum(&:double_size) }
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# using DoubleSize
|
|
36
|
+
# ["hello", "foo"].double_size # => 16
|
|
37
|
+
# ```
|
|
38
|
+
class Extension < Module
|
|
39
|
+
# @api private
|
|
40
|
+
class Mixin < Module # :nodoc:
|
|
41
|
+
attr_reader :extension, :target
|
|
42
|
+
|
|
43
|
+
def initialize(extension, target, &)
|
|
44
|
+
@extension = extension
|
|
45
|
+
@target = target
|
|
46
|
+
super(&)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def name = -"#{@extension.name}[#{@target.inspect}]"
|
|
50
|
+
|
|
51
|
+
def install
|
|
52
|
+
return if @target.ancestors.include?(self)
|
|
53
|
+
@target.prepend(self)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
private_constant :Mixin
|
|
57
|
+
|
|
58
|
+
# @overload define(*targets)
|
|
59
|
+
# Defines an extension for the given target classes.
|
|
60
|
+
# @param targets [Array<Class>] the target classes to define methods for
|
|
61
|
+
# @yield the block containing method definitions
|
|
62
|
+
# @yieldreceiver [Module, Refinement] the module/refinement used for extending the target class.
|
|
63
|
+
# @return [Extension] the newly created extension instance
|
|
64
|
+
# @see Extension#define
|
|
65
|
+
def self.define(...) = new { define(...) }
|
|
66
|
+
|
|
67
|
+
# Creates a new extension.
|
|
68
|
+
# @yield Optional block for `define` calls or adding methods to the extension itself.
|
|
69
|
+
# @yieldreceiver [Extension] the extension instance itself.
|
|
70
|
+
def initialize
|
|
71
|
+
check_state!
|
|
72
|
+
@definitions = Internal::StrictMap.new
|
|
73
|
+
@lock = Lock.new
|
|
74
|
+
@installed = Flag.new
|
|
75
|
+
super
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @api private
|
|
79
|
+
def [](target) = @definitions[target]
|
|
80
|
+
|
|
81
|
+
# Defines additional methods for a given target class.
|
|
82
|
+
#
|
|
83
|
+
# The given block will be invoked at least twice. Once in the context of a refinement for the target class,
|
|
84
|
+
# and once in the context of the mixin module that will be prepended to the target class.
|
|
85
|
+
#
|
|
86
|
+
# @example
|
|
87
|
+
# extension = Farce::Extension.new
|
|
88
|
+
# extension.define(String) { def double_size = size * 2 }
|
|
89
|
+
#
|
|
90
|
+
# module Namespace
|
|
91
|
+
# using extension
|
|
92
|
+
# String.method_defined?(:double_size) # => true
|
|
93
|
+
# end
|
|
94
|
+
#
|
|
95
|
+
# String.method_defined?(:double_size) # => false
|
|
96
|
+
# extension.install
|
|
97
|
+
# String.method_defined?(:double_size) # => true
|
|
98
|
+
#
|
|
99
|
+
# @param targets [Array<Class>] the target classes to define methods for
|
|
100
|
+
# @yield the block containing method definitions
|
|
101
|
+
# @yieldreceiver [Module, Refinement] the module/refinement used for extending the target class.
|
|
102
|
+
# @return [self] the extension instance
|
|
103
|
+
def define(*targets, &)
|
|
104
|
+
@lock.synchronize do
|
|
105
|
+
check_state!
|
|
106
|
+
targets.each do |target|
|
|
107
|
+
refine(target, &)
|
|
108
|
+
mixin = @definitions.store_if_absent(target) { Mixin.new(self, target) }
|
|
109
|
+
mixin.module_eval(&)
|
|
110
|
+
mixin.install if installed?
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
self
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Installs the extension globally.
|
|
117
|
+
# @return [void]
|
|
118
|
+
def install
|
|
119
|
+
@lock.synchronize do
|
|
120
|
+
return false if installed?
|
|
121
|
+
check_state!(allow_frozen: true)
|
|
122
|
+
@definitions.each_value(&:install)
|
|
123
|
+
yield if block_given?
|
|
124
|
+
@installed.set
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# @return [Boolean] whether the extension has been installed
|
|
129
|
+
def installed? = @installed.set?
|
|
130
|
+
|
|
131
|
+
# Freezes the extension.
|
|
132
|
+
#
|
|
133
|
+
# No {#define definitions} can be added after freezing the extension.
|
|
134
|
+
# @return [self] the frozen extension
|
|
135
|
+
def freeze
|
|
136
|
+
return self if frozen?
|
|
137
|
+
@lock.synchronize do
|
|
138
|
+
@definitions.freeze
|
|
139
|
+
super
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
|
|
145
|
+
def check_state!(allow_frozen: false)
|
|
146
|
+
raise Ractor::IsolationError, "must be called from main Ractor" if Internal.native_ractors? && !Ractor.main?
|
|
147
|
+
Internal::Freeze.check(self) unless allow_frozen
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -13,7 +13,10 @@ module Farce
|
|
|
13
13
|
# Take, put, and swap operate on the value staged in this attempt.
|
|
14
14
|
# An empty read, take, or swap, or a put into a full TMVar fails the
|
|
15
15
|
# attempt. Farce.transaction retries these conditions within its retry limit.
|
|
16
|
-
# The try_* methods return nil or false without failing
|
|
16
|
+
# The try_* methods return nil or false when unavailable without failing
|
|
17
|
+
# the attempt. Blocks passed to try_read and try_take run only when full,
|
|
18
|
+
# including for stored nil, and return the block's result.
|
|
19
|
+
# Create an empty TMVar with Ractor::TMVar.new and a full nil with .new(nil).
|
|
17
20
|
# Assigned values are made shareable, matching Ractor::TVar's setter.
|
|
18
21
|
#
|
|
19
22
|
# Run outside Ractor.atomically, as required by {RactorTVar}.
|
|
@@ -21,6 +21,7 @@ module Farce
|
|
|
21
21
|
INSTANCE = Freeze.publish(new)
|
|
22
22
|
DEFAULT_PORT = BasePort.new
|
|
23
23
|
|
|
24
|
+
def alive? = true
|
|
24
25
|
def default_port = DEFAULT_PORT
|
|
25
26
|
def inspect = "#<Farce::Ractor#1 running>"
|
|
26
27
|
def join = sleep
|
|
@@ -78,7 +79,7 @@ module Farce
|
|
|
78
79
|
ensure
|
|
79
80
|
state.mutex.synchronize do
|
|
80
81
|
state.monitors.each do |monitor|
|
|
81
|
-
monitor
|
|
82
|
+
FakeRactor.send_status(monitor, self, state.status)
|
|
82
83
|
end
|
|
83
84
|
state.monitors = nil
|
|
84
85
|
end
|
|
@@ -97,6 +98,8 @@ module Farce
|
|
|
97
98
|
Farce::Ractor[key] = value
|
|
98
99
|
end
|
|
99
100
|
|
|
101
|
+
def alive? = STATES[self].status == :running
|
|
102
|
+
|
|
100
103
|
def monitor(port) # rubocop:disable Naming/PredicateMethod
|
|
101
104
|
state = STATES[self]
|
|
102
105
|
|
|
@@ -108,7 +111,7 @@ module Farce
|
|
|
108
111
|
end
|
|
109
112
|
end
|
|
110
113
|
|
|
111
|
-
port
|
|
114
|
+
FakeRactor.send_status(port, self, state.status)
|
|
112
115
|
false
|
|
113
116
|
end
|
|
114
117
|
|
|
@@ -148,6 +151,11 @@ module Farce
|
|
|
148
151
|
undef clone
|
|
149
152
|
end
|
|
150
153
|
|
|
154
|
+
def self.send_status(port, ractor, status)
|
|
155
|
+
payload = System.ruby_version >= "4.1" ? [ractor, status].freeze : status
|
|
156
|
+
port << payload
|
|
157
|
+
end
|
|
158
|
+
|
|
151
159
|
def self.current
|
|
152
160
|
# JRuby fibers expose a backing thread with a different thread group.
|
|
153
161
|
thread = Internal.storage_thread(Thread.current)
|
|
@@ -82,15 +82,13 @@ module Farce
|
|
|
82
82
|
|
|
83
83
|
def unblock(_blocker, fiber) # rubocop:disable Naming/PredicateMethod
|
|
84
84
|
return false if @closed || !(token = current_wait(fiber))
|
|
85
|
-
|
|
86
|
-
wakeup
|
|
85
|
+
complete_wait(token, true)
|
|
87
86
|
true
|
|
88
87
|
end
|
|
89
88
|
|
|
90
89
|
def fiber_interrupt(fiber, exception) # rubocop:disable Naming/PredicateMethod
|
|
91
90
|
return false if @closed || !(token = current_wait(fiber))
|
|
92
|
-
|
|
93
|
-
wakeup
|
|
91
|
+
complete_wait(token, nil, exception)
|
|
94
92
|
true
|
|
95
93
|
end
|
|
96
94
|
|
|
@@ -202,6 +200,11 @@ module Farce
|
|
|
202
200
|
|
|
203
201
|
private
|
|
204
202
|
|
|
203
|
+
def complete_wait(token, value, error = nil)
|
|
204
|
+
@mailbox << Completion.new(token, value, error).freeze
|
|
205
|
+
wakeup
|
|
206
|
+
end
|
|
207
|
+
|
|
205
208
|
def finish_close
|
|
206
209
|
return if @closed
|
|
207
210
|
shutdown
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# shareable_constant_value: literal
|
|
3
|
+
# warn_indent: true
|
|
4
|
+
|
|
5
|
+
module Farce
|
|
6
|
+
# Special, write-only port that discards all messages.
|
|
7
|
+
# If the Ruby environment supports ports, this will be a real Port object.
|
|
8
|
+
# It can therefore be passed to any API expecting a `Ractor::Port`, including C code.
|
|
9
|
+
# Cannot be read from, but does not accumulate messages in memory.
|
|
10
|
+
# @return [Ractor::Port] Write-only port
|
|
11
|
+
NULL_PORT = Internal::NullPort.new
|
|
12
|
+
end
|
data/lib/farce/system.rb
CHANGED
|
@@ -7,8 +7,16 @@ require "etc"
|
|
|
7
7
|
module Farce
|
|
8
8
|
# Information about the system running Farce.
|
|
9
9
|
module System
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
ruby_version = Gem.ruby_version.release
|
|
11
|
+
ruby_version = ::Ractor.make_shareable(ruby_version, copy: true) if defined?(::Ractor)
|
|
12
|
+
RUBY_VERSION = ruby_version
|
|
13
|
+
WINDOWS = Gem.win_platform?
|
|
14
|
+
private_constant :RUBY_VERSION, :WINDOWS
|
|
15
|
+
|
|
16
|
+
# A Version object representing the current Ruby release, without prerelease suffixes.
|
|
17
|
+
# Safe to call from any Ractor.
|
|
18
|
+
# @return [#<=>, #to_s]
|
|
19
|
+
def self.ruby_version = RUBY_VERSION
|
|
12
20
|
|
|
13
21
|
# Whether the current operating system is Windows.
|
|
14
22
|
# Safe to call from any Ractor.
|
data/lib/farce/version.rb
CHANGED
data/lib/farce.rb
CHANGED
|
@@ -46,7 +46,7 @@ require "farce/system"
|
|
|
46
46
|
# defined?(VERSION) # => false
|
|
47
47
|
# ```
|
|
48
48
|
module Farce
|
|
49
|
-
include Internal::Autoloads
|
|
49
|
+
include Internal::Autoloads[null_port: :NULL_PORT]
|
|
50
50
|
|
|
51
51
|
# The valid storage scopes for local values and collections.
|
|
52
52
|
# @return [::Set<Symbol>]
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: farce
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Haase
|
|
@@ -24,13 +24,25 @@ files:
|
|
|
24
24
|
- README.md
|
|
25
25
|
- SECURITY.md
|
|
26
26
|
- docs/benchmarks.md
|
|
27
|
+
- docs/compatibility.md
|
|
28
|
+
- docs/concurrency.md
|
|
29
|
+
- docs/data-structures.md
|
|
27
30
|
- docs/gems/dry-types.md
|
|
28
31
|
- docs/gems/msgpack.md
|
|
29
32
|
- docs/gems/ractor-shim.md
|
|
33
|
+
- docs/installation.md
|
|
34
|
+
- docs/integrations.md
|
|
35
|
+
- docs/introduction.md
|
|
30
36
|
- docs/modes.md
|
|
37
|
+
- docs/scheduling.md
|
|
31
38
|
- docs/scopes.md
|
|
39
|
+
- docs/sharing.md
|
|
40
|
+
- docs/shims.md
|
|
41
|
+
- docs/utilities.md
|
|
42
|
+
- docs/variants-and-scopes.md
|
|
32
43
|
- docs/variants.md
|
|
33
44
|
- ext/ext_helper.rb
|
|
45
|
+
- ext/farce/LIBURING-LICENSE
|
|
34
46
|
- ext/farce/README.md
|
|
35
47
|
- ext/farce/atom.c
|
|
36
48
|
- ext/farce/bounded_map.c
|
|
@@ -45,9 +57,13 @@ files:
|
|
|
45
57
|
- ext/farce/extconf.rb
|
|
46
58
|
- ext/farce/farce.c
|
|
47
59
|
- ext/farce/flag.c
|
|
60
|
+
- ext/farce/futex.c
|
|
61
|
+
- ext/farce/futex.h
|
|
48
62
|
- ext/farce/io.c
|
|
49
63
|
- ext/farce/lock.c
|
|
50
64
|
- ext/farce/map.c
|
|
65
|
+
- ext/farce/native_wait.c
|
|
66
|
+
- ext/farce/native_wait.h
|
|
51
67
|
- ext/farce/priority_queue.c
|
|
52
68
|
- ext/farce/queue.c
|
|
53
69
|
- ext/farce/reactor.c
|
|
@@ -112,6 +128,7 @@ files:
|
|
|
112
128
|
- lib/farce/abstract/weak_set.rb
|
|
113
129
|
- lib/farce/abstract/weak_value_map.rb
|
|
114
130
|
- lib/farce/atom.rb
|
|
131
|
+
- lib/farce/backports.rb
|
|
115
132
|
- lib/farce/class_mirror.rb
|
|
116
133
|
- lib/farce/clock.rb
|
|
117
134
|
- lib/farce/config.rb
|
|
@@ -124,6 +141,7 @@ files:
|
|
|
124
141
|
- lib/farce/engine/jruby/lease_waiting.rb
|
|
125
142
|
- lib/farce/engine/jruby/map.rb
|
|
126
143
|
- lib/farce/engine/jruby/mutable_numeric_copy.rb
|
|
144
|
+
- lib/farce/engine/jruby/scheduler_synchronization.rb
|
|
127
145
|
- lib/farce/engine/jruby/signal.rb
|
|
128
146
|
- lib/farce/engine/jvm.rb
|
|
129
147
|
- lib/farce/engine/jvm/concurrent_weak_registry.rb
|
|
@@ -136,14 +154,18 @@ files:
|
|
|
136
154
|
- lib/farce/engine/jvm/types.rb
|
|
137
155
|
- lib/farce/engine/ruby.rb
|
|
138
156
|
- lib/farce/engine/ruby/3.4/fiber_scheduler.rb
|
|
157
|
+
- lib/farce/engine/ruby/3.4/null_port.rb
|
|
158
|
+
- lib/farce/engine/ruby/3.4/patch.rb
|
|
139
159
|
- lib/farce/engine/ruby/3.4/port.rb
|
|
140
160
|
- lib/farce/engine/ruby/3.4/ractor_methods.rb
|
|
141
161
|
- lib/farce/engine/ruby/3.4/ractor_selector.rb
|
|
142
162
|
- lib/farce/engine/ruby/3.4/vault.rb
|
|
163
|
+
- lib/farce/engine/ruby/4.0/null_port.rb
|
|
143
164
|
- lib/farce/engine/ruby/4.0/port.rb
|
|
144
165
|
- lib/farce/engine/ruby/4.0/ractor_methods.rb
|
|
145
166
|
- lib/farce/engine/ruby/4.0/ractor_selector.rb
|
|
146
167
|
- lib/farce/engine/ruby/4.0/vault.rb
|
|
168
|
+
- lib/farce/engine/ruby/4.1/null_port.rb
|
|
147
169
|
- lib/farce/engine/ruby/4.1/port.rb
|
|
148
170
|
- lib/farce/engine/ruby/4.1/ractor_methods.rb
|
|
149
171
|
- lib/farce/engine/ruby/4.1/ractor_selector.rb
|
|
@@ -172,12 +194,14 @@ files:
|
|
|
172
194
|
- lib/farce/engine/shared/lease_pool.rb
|
|
173
195
|
- lib/farce/engine/shared/main_scheduler.rb
|
|
174
196
|
- lib/farce/engine/shared/map_key_coordination.rb
|
|
197
|
+
- lib/farce/engine/shared/null_port.rb
|
|
175
198
|
- lib/farce/engine/shared/parallel_scheduler.rb
|
|
176
199
|
- lib/farce/engine/shared/port.rb
|
|
177
200
|
- lib/farce/engine/shared/portable_bounded_map.rb
|
|
178
201
|
- lib/farce/engine/shared/proxy_owner.rb
|
|
179
202
|
- lib/farce/engine/shared/queue.rb
|
|
180
203
|
- lib/farce/engine/shared/ractor_methods.rb
|
|
204
|
+
- lib/farce/engine/shared/ractor_selector.rb
|
|
181
205
|
- lib/farce/engine/shared/rebindable.rb
|
|
182
206
|
- lib/farce/engine/shared/strict_atom.rb
|
|
183
207
|
- lib/farce/engine/shared/strict_map.rb
|
|
@@ -216,6 +240,7 @@ files:
|
|
|
216
240
|
- lib/farce/envelope.rb
|
|
217
241
|
- lib/farce/error.rb
|
|
218
242
|
- lib/farce/exchanger.rb
|
|
243
|
+
- lib/farce/extension.rb
|
|
219
244
|
- lib/farce/flag.rb
|
|
220
245
|
- lib/farce/integrations.rb
|
|
221
246
|
- lib/farce/integrations/active_support.rb
|
|
@@ -344,6 +369,7 @@ files:
|
|
|
344
369
|
- lib/farce/mode_manager/smart_rule.rb
|
|
345
370
|
- lib/farce/molecule.rb
|
|
346
371
|
- lib/farce/mutable.rb
|
|
372
|
+
- lib/farce/null_port.rb
|
|
347
373
|
- lib/farce/pool.rb
|
|
348
374
|
- lib/farce/port.rb
|
|
349
375
|
- lib/farce/priority_queue.rb
|