farce 0.3.0-arm-linux-gnu → 0.4.0-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 +44 -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/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 +22 -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.0
|
|
5
5
|
platform: arm-linux-gnu
|
|
6
6
|
authors:
|
|
7
7
|
- Konstantin Haase
|
|
@@ -22,11 +22,22 @@ 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
|
|
32
43
|
- ext/farce/README.md
|
|
@@ -110,6 +121,7 @@ files:
|
|
|
110
121
|
- lib/farce/abstract/weak_set.rb
|
|
111
122
|
- lib/farce/abstract/weak_value_map.rb
|
|
112
123
|
- lib/farce/atom.rb
|
|
124
|
+
- lib/farce/backports.rb
|
|
113
125
|
- lib/farce/class_mirror.rb
|
|
114
126
|
- lib/farce/clock.rb
|
|
115
127
|
- lib/farce/config.rb
|
|
@@ -122,6 +134,7 @@ files:
|
|
|
122
134
|
- lib/farce/engine/jruby/lease_waiting.rb
|
|
123
135
|
- lib/farce/engine/jruby/map.rb
|
|
124
136
|
- lib/farce/engine/jruby/mutable_numeric_copy.rb
|
|
137
|
+
- lib/farce/engine/jruby/scheduler_synchronization.rb
|
|
125
138
|
- lib/farce/engine/jruby/signal.rb
|
|
126
139
|
- lib/farce/engine/jvm.rb
|
|
127
140
|
- lib/farce/engine/jvm/concurrent_weak_registry.rb
|
|
@@ -135,17 +148,21 @@ files:
|
|
|
135
148
|
- lib/farce/engine/ruby.rb
|
|
136
149
|
- lib/farce/engine/ruby/3.4/farce.so
|
|
137
150
|
- lib/farce/engine/ruby/3.4/fiber_scheduler.rb
|
|
151
|
+
- lib/farce/engine/ruby/3.4/null_port.rb
|
|
152
|
+
- lib/farce/engine/ruby/3.4/patch.rb
|
|
138
153
|
- lib/farce/engine/ruby/3.4/port.rb
|
|
139
154
|
- lib/farce/engine/ruby/3.4/ractor_methods.rb
|
|
140
155
|
- lib/farce/engine/ruby/3.4/ractor_selector.rb
|
|
141
156
|
- lib/farce/engine/ruby/3.4/rebind.so
|
|
142
157
|
- lib/farce/engine/ruby/3.4/vault.rb
|
|
143
158
|
- lib/farce/engine/ruby/4.0/farce.so
|
|
159
|
+
- lib/farce/engine/ruby/4.0/null_port.rb
|
|
144
160
|
- lib/farce/engine/ruby/4.0/port.rb
|
|
145
161
|
- lib/farce/engine/ruby/4.0/ractor_methods.rb
|
|
146
162
|
- lib/farce/engine/ruby/4.0/ractor_selector.rb
|
|
147
163
|
- lib/farce/engine/ruby/4.0/rebind.so
|
|
148
164
|
- lib/farce/engine/ruby/4.0/vault.rb
|
|
165
|
+
- lib/farce/engine/ruby/4.1/null_port.rb
|
|
149
166
|
- lib/farce/engine/ruby/4.1/port.rb
|
|
150
167
|
- lib/farce/engine/ruby/4.1/ractor_methods.rb
|
|
151
168
|
- lib/farce/engine/ruby/4.1/ractor_selector.rb
|
|
@@ -174,12 +191,14 @@ files:
|
|
|
174
191
|
- lib/farce/engine/shared/lease_pool.rb
|
|
175
192
|
- lib/farce/engine/shared/main_scheduler.rb
|
|
176
193
|
- lib/farce/engine/shared/map_key_coordination.rb
|
|
194
|
+
- lib/farce/engine/shared/null_port.rb
|
|
177
195
|
- lib/farce/engine/shared/parallel_scheduler.rb
|
|
178
196
|
- lib/farce/engine/shared/port.rb
|
|
179
197
|
- lib/farce/engine/shared/portable_bounded_map.rb
|
|
180
198
|
- lib/farce/engine/shared/proxy_owner.rb
|
|
181
199
|
- lib/farce/engine/shared/queue.rb
|
|
182
200
|
- lib/farce/engine/shared/ractor_methods.rb
|
|
201
|
+
- lib/farce/engine/shared/ractor_selector.rb
|
|
183
202
|
- lib/farce/engine/shared/rebindable.rb
|
|
184
203
|
- lib/farce/engine/shared/strict_atom.rb
|
|
185
204
|
- lib/farce/engine/shared/strict_map.rb
|
|
@@ -218,6 +237,7 @@ files:
|
|
|
218
237
|
- lib/farce/envelope.rb
|
|
219
238
|
- lib/farce/error.rb
|
|
220
239
|
- lib/farce/exchanger.rb
|
|
240
|
+
- lib/farce/extension.rb
|
|
221
241
|
- lib/farce/flag.rb
|
|
222
242
|
- lib/farce/integrations.rb
|
|
223
243
|
- lib/farce/integrations/active_support.rb
|
|
@@ -346,6 +366,7 @@ files:
|
|
|
346
366
|
- lib/farce/mode_manager/smart_rule.rb
|
|
347
367
|
- lib/farce/molecule.rb
|
|
348
368
|
- lib/farce/mutable.rb
|
|
369
|
+
- lib/farce/null_port.rb
|
|
349
370
|
- lib/farce/pool.rb
|
|
350
371
|
- lib/farce/port.rb
|
|
351
372
|
- lib/farce/priority_queue.rb
|