farce 0.3.0-arm-linux-gnu → 0.4.1-arm-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 +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/farce.so +0 -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/farce.so +0 -0
- 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: arm-linux-gnu
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Haase
|
|
@@ -22,13 +22,25 @@ files:
|
|
|
22
22
|
- README.md
|
|
23
23
|
- SECURITY.md
|
|
24
24
|
- docs/benchmarks.md
|
|
25
|
+
- docs/compatibility.md
|
|
26
|
+
- docs/concurrency.md
|
|
27
|
+
- docs/data-structures.md
|
|
25
28
|
- docs/gems/dry-types.md
|
|
26
29
|
- docs/gems/msgpack.md
|
|
27
30
|
- docs/gems/ractor-shim.md
|
|
31
|
+
- docs/installation.md
|
|
32
|
+
- docs/integrations.md
|
|
33
|
+
- docs/introduction.md
|
|
28
34
|
- docs/modes.md
|
|
35
|
+
- docs/scheduling.md
|
|
29
36
|
- docs/scopes.md
|
|
37
|
+
- docs/sharing.md
|
|
38
|
+
- docs/shims.md
|
|
39
|
+
- docs/utilities.md
|
|
40
|
+
- docs/variants-and-scopes.md
|
|
30
41
|
- docs/variants.md
|
|
31
42
|
- ext/ext_helper.rb
|
|
43
|
+
- ext/farce/LIBURING-LICENSE
|
|
32
44
|
- ext/farce/README.md
|
|
33
45
|
- ext/farce/atom.c
|
|
34
46
|
- ext/farce/bounded_map.c
|
|
@@ -43,9 +55,13 @@ files:
|
|
|
43
55
|
- ext/farce/extconf.rb
|
|
44
56
|
- ext/farce/farce.c
|
|
45
57
|
- ext/farce/flag.c
|
|
58
|
+
- ext/farce/futex.c
|
|
59
|
+
- ext/farce/futex.h
|
|
46
60
|
- ext/farce/io.c
|
|
47
61
|
- ext/farce/lock.c
|
|
48
62
|
- ext/farce/map.c
|
|
63
|
+
- ext/farce/native_wait.c
|
|
64
|
+
- ext/farce/native_wait.h
|
|
49
65
|
- ext/farce/priority_queue.c
|
|
50
66
|
- ext/farce/queue.c
|
|
51
67
|
- ext/farce/reactor.c
|
|
@@ -110,6 +126,7 @@ files:
|
|
|
110
126
|
- lib/farce/abstract/weak_set.rb
|
|
111
127
|
- lib/farce/abstract/weak_value_map.rb
|
|
112
128
|
- lib/farce/atom.rb
|
|
129
|
+
- lib/farce/backports.rb
|
|
113
130
|
- lib/farce/class_mirror.rb
|
|
114
131
|
- lib/farce/clock.rb
|
|
115
132
|
- lib/farce/config.rb
|
|
@@ -122,6 +139,7 @@ files:
|
|
|
122
139
|
- lib/farce/engine/jruby/lease_waiting.rb
|
|
123
140
|
- lib/farce/engine/jruby/map.rb
|
|
124
141
|
- lib/farce/engine/jruby/mutable_numeric_copy.rb
|
|
142
|
+
- lib/farce/engine/jruby/scheduler_synchronization.rb
|
|
125
143
|
- lib/farce/engine/jruby/signal.rb
|
|
126
144
|
- lib/farce/engine/jvm.rb
|
|
127
145
|
- lib/farce/engine/jvm/concurrent_weak_registry.rb
|
|
@@ -135,17 +153,21 @@ files:
|
|
|
135
153
|
- lib/farce/engine/ruby.rb
|
|
136
154
|
- lib/farce/engine/ruby/3.4/farce.so
|
|
137
155
|
- lib/farce/engine/ruby/3.4/fiber_scheduler.rb
|
|
156
|
+
- lib/farce/engine/ruby/3.4/null_port.rb
|
|
157
|
+
- lib/farce/engine/ruby/3.4/patch.rb
|
|
138
158
|
- lib/farce/engine/ruby/3.4/port.rb
|
|
139
159
|
- lib/farce/engine/ruby/3.4/ractor_methods.rb
|
|
140
160
|
- lib/farce/engine/ruby/3.4/ractor_selector.rb
|
|
141
161
|
- lib/farce/engine/ruby/3.4/rebind.so
|
|
142
162
|
- lib/farce/engine/ruby/3.4/vault.rb
|
|
143
163
|
- lib/farce/engine/ruby/4.0/farce.so
|
|
164
|
+
- lib/farce/engine/ruby/4.0/null_port.rb
|
|
144
165
|
- lib/farce/engine/ruby/4.0/port.rb
|
|
145
166
|
- lib/farce/engine/ruby/4.0/ractor_methods.rb
|
|
146
167
|
- lib/farce/engine/ruby/4.0/ractor_selector.rb
|
|
147
168
|
- lib/farce/engine/ruby/4.0/rebind.so
|
|
148
169
|
- lib/farce/engine/ruby/4.0/vault.rb
|
|
170
|
+
- lib/farce/engine/ruby/4.1/null_port.rb
|
|
149
171
|
- lib/farce/engine/ruby/4.1/port.rb
|
|
150
172
|
- lib/farce/engine/ruby/4.1/ractor_methods.rb
|
|
151
173
|
- lib/farce/engine/ruby/4.1/ractor_selector.rb
|
|
@@ -174,12 +196,14 @@ files:
|
|
|
174
196
|
- lib/farce/engine/shared/lease_pool.rb
|
|
175
197
|
- lib/farce/engine/shared/main_scheduler.rb
|
|
176
198
|
- lib/farce/engine/shared/map_key_coordination.rb
|
|
199
|
+
- lib/farce/engine/shared/null_port.rb
|
|
177
200
|
- lib/farce/engine/shared/parallel_scheduler.rb
|
|
178
201
|
- lib/farce/engine/shared/port.rb
|
|
179
202
|
- lib/farce/engine/shared/portable_bounded_map.rb
|
|
180
203
|
- lib/farce/engine/shared/proxy_owner.rb
|
|
181
204
|
- lib/farce/engine/shared/queue.rb
|
|
182
205
|
- lib/farce/engine/shared/ractor_methods.rb
|
|
206
|
+
- lib/farce/engine/shared/ractor_selector.rb
|
|
183
207
|
- lib/farce/engine/shared/rebindable.rb
|
|
184
208
|
- lib/farce/engine/shared/strict_atom.rb
|
|
185
209
|
- lib/farce/engine/shared/strict_map.rb
|
|
@@ -218,6 +242,7 @@ files:
|
|
|
218
242
|
- lib/farce/envelope.rb
|
|
219
243
|
- lib/farce/error.rb
|
|
220
244
|
- lib/farce/exchanger.rb
|
|
245
|
+
- lib/farce/extension.rb
|
|
221
246
|
- lib/farce/flag.rb
|
|
222
247
|
- lib/farce/integrations.rb
|
|
223
248
|
- lib/farce/integrations/active_support.rb
|
|
@@ -346,6 +371,7 @@ files:
|
|
|
346
371
|
- lib/farce/mode_manager/smart_rule.rb
|
|
347
372
|
- lib/farce/molecule.rb
|
|
348
373
|
- lib/farce/mutable.rb
|
|
374
|
+
- lib/farce/null_port.rb
|
|
349
375
|
- lib/farce/pool.rb
|
|
350
376
|
- lib/farce/port.rb
|
|
351
377
|
- lib/farce/priority_queue.rb
|