Module: Farce::Backports
- Includes:
- Extension.new
- Defined in:
- lib/farce/backports.rb
Overview
Backports for Ractor and related functionality to older Ruby versions.
Activating Backports
There are three ways of using these backports:
- Activating them globally via: Backports.install
- Using them within a specific scope via refinements:
using Farce::Backports - Calling methods on
Farce::Backportsdirectly
Only the first method will also define the global constants Ractor and Ractor::Port
if they are not natively available.
Class Method Summary collapse
-
.alive?(ractor) ⇒ Boolean
Backport for Ractor#alive?.
-
.default_port(ractor) ⇒ Ractor::Port
Backport for Ractor.default_port.
-
.install ⇒ BasicObject
Installs the Farce backports for Ractor and Ractor::Port globally.
-
.join(ractor) ⇒ Ractor
Backport for Ractor#join.
-
.monitor(ractor, port) ⇒ Boolean
Backport for Ractor#monitor.
-
.receive(ractor_or_port, timeout: nil) ⇒ Object
Backport for the optional timeout parameter of Ractor#receive and Ractor::Port#receive.
-
.select ⇒ BasicObject
Backport for the optional timeout parameter of Ractor.select.
-
.unmonitor(ractor, port) ⇒ Ractor
Backport for Ractor#unmonitor.
-
.value(ractor) ⇒ Object
Backport for Ractor#value.
Class Method Details
.alive?(ractor) ⇒ Boolean
Backport for Ractor#alive?
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/farce/backports.rb', line 136 module Backports # @!visibility private Extension = Farce::Extension.new private_constant :Extension include Extension if Internal.native_ractors? if needs_timeouts = ::Ractor.instance_method(:receive).arity.zero? Extension.define(::Ractor) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end Extension.define(::Ractor.singleton_class) do def select(*sources, timeout: nil, **) # The selector helper must reach Ruby's native wait without reentering itself. return super(*sources, **) if timeout.nil? && (Internal.native_ports? || sources.all?(::Ractor)) Farce::Ractor.select(*sources, timeout:, **) end end def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) return ractor_or_port.receive if timeout.nil? return ractor_or_port.receive(timeout:) unless Internal.native_ports? Internal::RactorSelector.current.ractor_receive(ractor_or_port, timeout:) end end if Internal.native_ports? unless ::Ractor.method_defined?(:alive?) Extension.define(::Ractor) { def alive? = Backports.alive?(self) } def self.alive?(ractor) ractor.monitor(NULL_PORT) ensure ractor.unmonitor(NULL_PORT) end end if needs_timeouts Extension.define(::Ractor::Port) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end end else Extension.define(::Ractor) do def alive? = Backports.alive?(self) def default_port = Backports.default_port(self) def join = Backports.join(self) def monitor(port) = Backports.monitor(self, port) def unmonitor(port) = Backports.unmonitor(self, port) def value = Backports.value(self) end def self.alive?(ractor) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.alive? if state !ractor.inspect.end_with?("terminated>") end def self.default_port(ractor) = Farce::Ractor::Port.new(ractor) def self.join(ractor) Internal::RactorState.for(ractor)&.join ractor end def self.monitor(ractor, port) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.monitor(port) if state raise Ractor::Error, "#{ractor.inspect} cannot be monitored" unless ractor.inspect.end_with?("terminated>") success = true begin ractor.take rescue Ractor::ClosedError # no-op rescue Ractor::RemoteError success = false end port.send(success ? :exited : :aborted) false end def self.unmonitor(ractor, port) Internal::RactorState.for(ractor)&.unmonitor(port) ractor end def self.value(ractor) Internal::RactorState.for(ractor)&.join values = ::Ractor.store_if_absent("Ractor#value") { ObjectSpace::WeakKeyMap.new } entry = values[ractor] ||= [Mutex.new] entry.first.synchronize { entry << ractor.take if entry.size == 1 } entry[1] end end end %i[alive? default_port join monitor unmonitor value].each do |method| next if respond_to?(method) class_eval <<~RUBY, __FILE__, __LINE__ + 1 def self.#{method}(ractor, ...) = ractor.#{method}(...) RUBY end unless respond_to?(:receive) def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) timeout.nil? ? ractor_or_port.receive : ractor_or_port.receive(timeout:) end end def self.select(...) = Farce::Ractor.select(...) # Installs the Farce backports for Ractor and Ractor::Port globally. def self.install Extension.install do if Internal.native_ractors? ::Ractor.const_set(:Port, Farce::Ractor::Port) unless Internal.native_ports? else Object.const_set(:Ractor, Farce::Ractor) end end end end |
.default_port(ractor) ⇒ Ractor::Port
Backport for Ractor.default_port
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/farce/backports.rb', line 136 module Backports # @!visibility private Extension = Farce::Extension.new private_constant :Extension include Extension if Internal.native_ractors? if needs_timeouts = ::Ractor.instance_method(:receive).arity.zero? Extension.define(::Ractor) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end Extension.define(::Ractor.singleton_class) do def select(*sources, timeout: nil, **) # The selector helper must reach Ruby's native wait without reentering itself. return super(*sources, **) if timeout.nil? && (Internal.native_ports? || sources.all?(::Ractor)) Farce::Ractor.select(*sources, timeout:, **) end end def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) return ractor_or_port.receive if timeout.nil? return ractor_or_port.receive(timeout:) unless Internal.native_ports? Internal::RactorSelector.current.ractor_receive(ractor_or_port, timeout:) end end if Internal.native_ports? unless ::Ractor.method_defined?(:alive?) Extension.define(::Ractor) { def alive? = Backports.alive?(self) } def self.alive?(ractor) ractor.monitor(NULL_PORT) ensure ractor.unmonitor(NULL_PORT) end end if needs_timeouts Extension.define(::Ractor::Port) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end end else Extension.define(::Ractor) do def alive? = Backports.alive?(self) def default_port = Backports.default_port(self) def join = Backports.join(self) def monitor(port) = Backports.monitor(self, port) def unmonitor(port) = Backports.unmonitor(self, port) def value = Backports.value(self) end def self.alive?(ractor) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.alive? if state !ractor.inspect.end_with?("terminated>") end def self.default_port(ractor) = Farce::Ractor::Port.new(ractor) def self.join(ractor) Internal::RactorState.for(ractor)&.join ractor end def self.monitor(ractor, port) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.monitor(port) if state raise Ractor::Error, "#{ractor.inspect} cannot be monitored" unless ractor.inspect.end_with?("terminated>") success = true begin ractor.take rescue Ractor::ClosedError # no-op rescue Ractor::RemoteError success = false end port.send(success ? :exited : :aborted) false end def self.unmonitor(ractor, port) Internal::RactorState.for(ractor)&.unmonitor(port) ractor end def self.value(ractor) Internal::RactorState.for(ractor)&.join values = ::Ractor.store_if_absent("Ractor#value") { ObjectSpace::WeakKeyMap.new } entry = values[ractor] ||= [Mutex.new] entry.first.synchronize { entry << ractor.take if entry.size == 1 } entry[1] end end end %i[alive? default_port join monitor unmonitor value].each do |method| next if respond_to?(method) class_eval <<~RUBY, __FILE__, __LINE__ + 1 def self.#{method}(ractor, ...) = ractor.#{method}(...) RUBY end unless respond_to?(:receive) def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) timeout.nil? ? ractor_or_port.receive : ractor_or_port.receive(timeout:) end end def self.select(...) = Farce::Ractor.select(...) # Installs the Farce backports for Ractor and Ractor::Port globally. def self.install Extension.install do if Internal.native_ractors? ::Ractor.const_set(:Port, Farce::Ractor::Port) unless Internal.native_ports? else Object.const_set(:Ractor, Farce::Ractor) end end end end |
.install ⇒ BasicObject
Installs the Farce backports for Ractor and Ractor::Port globally.
264 265 266 267 268 269 270 271 272 |
# File 'lib/farce/backports.rb', line 264 def self.install Extension.install do if Internal.native_ractors? ::Ractor.const_set(:Port, Farce::Ractor::Port) unless Internal.native_ports? else Object.const_set(:Ractor, Farce::Ractor) end end end |
.join(ractor) ⇒ Ractor
Backport for Ractor#join
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/farce/backports.rb', line 136 module Backports # @!visibility private Extension = Farce::Extension.new private_constant :Extension include Extension if Internal.native_ractors? if needs_timeouts = ::Ractor.instance_method(:receive).arity.zero? Extension.define(::Ractor) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end Extension.define(::Ractor.singleton_class) do def select(*sources, timeout: nil, **) # The selector helper must reach Ruby's native wait without reentering itself. return super(*sources, **) if timeout.nil? && (Internal.native_ports? || sources.all?(::Ractor)) Farce::Ractor.select(*sources, timeout:, **) end end def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) return ractor_or_port.receive if timeout.nil? return ractor_or_port.receive(timeout:) unless Internal.native_ports? Internal::RactorSelector.current.ractor_receive(ractor_or_port, timeout:) end end if Internal.native_ports? unless ::Ractor.method_defined?(:alive?) Extension.define(::Ractor) { def alive? = Backports.alive?(self) } def self.alive?(ractor) ractor.monitor(NULL_PORT) ensure ractor.unmonitor(NULL_PORT) end end if needs_timeouts Extension.define(::Ractor::Port) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end end else Extension.define(::Ractor) do def alive? = Backports.alive?(self) def default_port = Backports.default_port(self) def join = Backports.join(self) def monitor(port) = Backports.monitor(self, port) def unmonitor(port) = Backports.unmonitor(self, port) def value = Backports.value(self) end def self.alive?(ractor) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.alive? if state !ractor.inspect.end_with?("terminated>") end def self.default_port(ractor) = Farce::Ractor::Port.new(ractor) def self.join(ractor) Internal::RactorState.for(ractor)&.join ractor end def self.monitor(ractor, port) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.monitor(port) if state raise Ractor::Error, "#{ractor.inspect} cannot be monitored" unless ractor.inspect.end_with?("terminated>") success = true begin ractor.take rescue Ractor::ClosedError # no-op rescue Ractor::RemoteError success = false end port.send(success ? :exited : :aborted) false end def self.unmonitor(ractor, port) Internal::RactorState.for(ractor)&.unmonitor(port) ractor end def self.value(ractor) Internal::RactorState.for(ractor)&.join values = ::Ractor.store_if_absent("Ractor#value") { ObjectSpace::WeakKeyMap.new } entry = values[ractor] ||= [Mutex.new] entry.first.synchronize { entry << ractor.take if entry.size == 1 } entry[1] end end end %i[alive? default_port join monitor unmonitor value].each do |method| next if respond_to?(method) class_eval <<~RUBY, __FILE__, __LINE__ + 1 def self.#{method}(ractor, ...) = ractor.#{method}(...) RUBY end unless respond_to?(:receive) def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) timeout.nil? ? ractor_or_port.receive : ractor_or_port.receive(timeout:) end end def self.select(...) = Farce::Ractor.select(...) # Installs the Farce backports for Ractor and Ractor::Port globally. def self.install Extension.install do if Internal.native_ractors? ::Ractor.const_set(:Port, Farce::Ractor::Port) unless Internal.native_ports? else Object.const_set(:Ractor, Farce::Ractor) end end end end |
.monitor(ractor, port) ⇒ Boolean
Backport for Ractor#monitor
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/farce/backports.rb', line 136 module Backports # @!visibility private Extension = Farce::Extension.new private_constant :Extension include Extension if Internal.native_ractors? if needs_timeouts = ::Ractor.instance_method(:receive).arity.zero? Extension.define(::Ractor) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end Extension.define(::Ractor.singleton_class) do def select(*sources, timeout: nil, **) # The selector helper must reach Ruby's native wait without reentering itself. return super(*sources, **) if timeout.nil? && (Internal.native_ports? || sources.all?(::Ractor)) Farce::Ractor.select(*sources, timeout:, **) end end def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) return ractor_or_port.receive if timeout.nil? return ractor_or_port.receive(timeout:) unless Internal.native_ports? Internal::RactorSelector.current.ractor_receive(ractor_or_port, timeout:) end end if Internal.native_ports? unless ::Ractor.method_defined?(:alive?) Extension.define(::Ractor) { def alive? = Backports.alive?(self) } def self.alive?(ractor) ractor.monitor(NULL_PORT) ensure ractor.unmonitor(NULL_PORT) end end if needs_timeouts Extension.define(::Ractor::Port) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end end else Extension.define(::Ractor) do def alive? = Backports.alive?(self) def default_port = Backports.default_port(self) def join = Backports.join(self) def monitor(port) = Backports.monitor(self, port) def unmonitor(port) = Backports.unmonitor(self, port) def value = Backports.value(self) end def self.alive?(ractor) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.alive? if state !ractor.inspect.end_with?("terminated>") end def self.default_port(ractor) = Farce::Ractor::Port.new(ractor) def self.join(ractor) Internal::RactorState.for(ractor)&.join ractor end def self.monitor(ractor, port) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.monitor(port) if state raise Ractor::Error, "#{ractor.inspect} cannot be monitored" unless ractor.inspect.end_with?("terminated>") success = true begin ractor.take rescue Ractor::ClosedError # no-op rescue Ractor::RemoteError success = false end port.send(success ? :exited : :aborted) false end def self.unmonitor(ractor, port) Internal::RactorState.for(ractor)&.unmonitor(port) ractor end def self.value(ractor) Internal::RactorState.for(ractor)&.join values = ::Ractor.store_if_absent("Ractor#value") { ObjectSpace::WeakKeyMap.new } entry = values[ractor] ||= [Mutex.new] entry.first.synchronize { entry << ractor.take if entry.size == 1 } entry[1] end end end %i[alive? default_port join monitor unmonitor value].each do |method| next if respond_to?(method) class_eval <<~RUBY, __FILE__, __LINE__ + 1 def self.#{method}(ractor, ...) = ractor.#{method}(...) RUBY end unless respond_to?(:receive) def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) timeout.nil? ? ractor_or_port.receive : ractor_or_port.receive(timeout:) end end def self.select(...) = Farce::Ractor.select(...) # Installs the Farce backports for Ractor and Ractor::Port globally. def self.install Extension.install do if Internal.native_ractors? ::Ractor.const_set(:Port, Farce::Ractor::Port) unless Internal.native_ports? else Object.const_set(:Ractor, Farce::Ractor) end end end end |
.receive(ractor_or_port, timeout: nil) ⇒ Object
Backport for the optional timeout parameter of Ractor#receive and Ractor::Port#receive
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/farce/backports.rb', line 136 module Backports # @!visibility private Extension = Farce::Extension.new private_constant :Extension include Extension if Internal.native_ractors? if needs_timeouts = ::Ractor.instance_method(:receive).arity.zero? Extension.define(::Ractor) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end Extension.define(::Ractor.singleton_class) do def select(*sources, timeout: nil, **) # The selector helper must reach Ruby's native wait without reentering itself. return super(*sources, **) if timeout.nil? && (Internal.native_ports? || sources.all?(::Ractor)) Farce::Ractor.select(*sources, timeout:, **) end end def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) return ractor_or_port.receive if timeout.nil? return ractor_or_port.receive(timeout:) unless Internal.native_ports? Internal::RactorSelector.current.ractor_receive(ractor_or_port, timeout:) end end if Internal.native_ports? unless ::Ractor.method_defined?(:alive?) Extension.define(::Ractor) { def alive? = Backports.alive?(self) } def self.alive?(ractor) ractor.monitor(NULL_PORT) ensure ractor.unmonitor(NULL_PORT) end end if needs_timeouts Extension.define(::Ractor::Port) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end end else Extension.define(::Ractor) do def alive? = Backports.alive?(self) def default_port = Backports.default_port(self) def join = Backports.join(self) def monitor(port) = Backports.monitor(self, port) def unmonitor(port) = Backports.unmonitor(self, port) def value = Backports.value(self) end def self.alive?(ractor) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.alive? if state !ractor.inspect.end_with?("terminated>") end def self.default_port(ractor) = Farce::Ractor::Port.new(ractor) def self.join(ractor) Internal::RactorState.for(ractor)&.join ractor end def self.monitor(ractor, port) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.monitor(port) if state raise Ractor::Error, "#{ractor.inspect} cannot be monitored" unless ractor.inspect.end_with?("terminated>") success = true begin ractor.take rescue Ractor::ClosedError # no-op rescue Ractor::RemoteError success = false end port.send(success ? :exited : :aborted) false end def self.unmonitor(ractor, port) Internal::RactorState.for(ractor)&.unmonitor(port) ractor end def self.value(ractor) Internal::RactorState.for(ractor)&.join values = ::Ractor.store_if_absent("Ractor#value") { ObjectSpace::WeakKeyMap.new } entry = values[ractor] ||= [Mutex.new] entry.first.synchronize { entry << ractor.take if entry.size == 1 } entry[1] end end end %i[alive? default_port join monitor unmonitor value].each do |method| next if respond_to?(method) class_eval <<~RUBY, __FILE__, __LINE__ + 1 def self.#{method}(ractor, ...) = ractor.#{method}(...) RUBY end unless respond_to?(:receive) def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) timeout.nil? ? ractor_or_port.receive : ractor_or_port.receive(timeout:) end end def self.select(...) = Farce::Ractor.select(...) # Installs the Farce backports for Ractor and Ractor::Port globally. def self.install Extension.install do if Internal.native_ractors? ::Ractor.const_set(:Port, Farce::Ractor::Port) unless Internal.native_ports? else Object.const_set(:Ractor, Farce::Ractor) end end end end |
.select ⇒ BasicObject
Backport for the optional timeout parameter of Ractor.select
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/farce/backports.rb', line 136 module Backports # @!visibility private Extension = Farce::Extension.new private_constant :Extension include Extension if Internal.native_ractors? if needs_timeouts = ::Ractor.instance_method(:receive).arity.zero? Extension.define(::Ractor) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end Extension.define(::Ractor.singleton_class) do def select(*sources, timeout: nil, **) # The selector helper must reach Ruby's native wait without reentering itself. return super(*sources, **) if timeout.nil? && (Internal.native_ports? || sources.all?(::Ractor)) Farce::Ractor.select(*sources, timeout:, **) end end def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) return ractor_or_port.receive if timeout.nil? return ractor_or_port.receive(timeout:) unless Internal.native_ports? Internal::RactorSelector.current.ractor_receive(ractor_or_port, timeout:) end end if Internal.native_ports? unless ::Ractor.method_defined?(:alive?) Extension.define(::Ractor) { def alive? = Backports.alive?(self) } def self.alive?(ractor) ractor.monitor(NULL_PORT) ensure ractor.unmonitor(NULL_PORT) end end if needs_timeouts Extension.define(::Ractor::Port) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end end else Extension.define(::Ractor) do def alive? = Backports.alive?(self) def default_port = Backports.default_port(self) def join = Backports.join(self) def monitor(port) = Backports.monitor(self, port) def unmonitor(port) = Backports.unmonitor(self, port) def value = Backports.value(self) end def self.alive?(ractor) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.alive? if state !ractor.inspect.end_with?("terminated>") end def self.default_port(ractor) = Farce::Ractor::Port.new(ractor) def self.join(ractor) Internal::RactorState.for(ractor)&.join ractor end def self.monitor(ractor, port) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.monitor(port) if state raise Ractor::Error, "#{ractor.inspect} cannot be monitored" unless ractor.inspect.end_with?("terminated>") success = true begin ractor.take rescue Ractor::ClosedError # no-op rescue Ractor::RemoteError success = false end port.send(success ? :exited : :aborted) false end def self.unmonitor(ractor, port) Internal::RactorState.for(ractor)&.unmonitor(port) ractor end def self.value(ractor) Internal::RactorState.for(ractor)&.join values = ::Ractor.store_if_absent("Ractor#value") { ObjectSpace::WeakKeyMap.new } entry = values[ractor] ||= [Mutex.new] entry.first.synchronize { entry << ractor.take if entry.size == 1 } entry[1] end end end %i[alive? default_port join monitor unmonitor value].each do |method| next if respond_to?(method) class_eval <<~RUBY, __FILE__, __LINE__ + 1 def self.#{method}(ractor, ...) = ractor.#{method}(...) RUBY end unless respond_to?(:receive) def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) timeout.nil? ? ractor_or_port.receive : ractor_or_port.receive(timeout:) end end def self.select(...) = Farce::Ractor.select(...) # Installs the Farce backports for Ractor and Ractor::Port globally. def self.install Extension.install do if Internal.native_ractors? ::Ractor.const_set(:Port, Farce::Ractor::Port) unless Internal.native_ports? else Object.const_set(:Ractor, Farce::Ractor) end end end end |
.unmonitor(ractor, port) ⇒ Ractor
Backport for Ractor#unmonitor
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/farce/backports.rb', line 136 module Backports # @!visibility private Extension = Farce::Extension.new private_constant :Extension include Extension if Internal.native_ractors? if needs_timeouts = ::Ractor.instance_method(:receive).arity.zero? Extension.define(::Ractor) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end Extension.define(::Ractor.singleton_class) do def select(*sources, timeout: nil, **) # The selector helper must reach Ruby's native wait without reentering itself. return super(*sources, **) if timeout.nil? && (Internal.native_ports? || sources.all?(::Ractor)) Farce::Ractor.select(*sources, timeout:, **) end end def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) return ractor_or_port.receive if timeout.nil? return ractor_or_port.receive(timeout:) unless Internal.native_ports? Internal::RactorSelector.current.ractor_receive(ractor_or_port, timeout:) end end if Internal.native_ports? unless ::Ractor.method_defined?(:alive?) Extension.define(::Ractor) { def alive? = Backports.alive?(self) } def self.alive?(ractor) ractor.monitor(NULL_PORT) ensure ractor.unmonitor(NULL_PORT) end end if needs_timeouts Extension.define(::Ractor::Port) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end end else Extension.define(::Ractor) do def alive? = Backports.alive?(self) def default_port = Backports.default_port(self) def join = Backports.join(self) def monitor(port) = Backports.monitor(self, port) def unmonitor(port) = Backports.unmonitor(self, port) def value = Backports.value(self) end def self.alive?(ractor) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.alive? if state !ractor.inspect.end_with?("terminated>") end def self.default_port(ractor) = Farce::Ractor::Port.new(ractor) def self.join(ractor) Internal::RactorState.for(ractor)&.join ractor end def self.monitor(ractor, port) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.monitor(port) if state raise Ractor::Error, "#{ractor.inspect} cannot be monitored" unless ractor.inspect.end_with?("terminated>") success = true begin ractor.take rescue Ractor::ClosedError # no-op rescue Ractor::RemoteError success = false end port.send(success ? :exited : :aborted) false end def self.unmonitor(ractor, port) Internal::RactorState.for(ractor)&.unmonitor(port) ractor end def self.value(ractor) Internal::RactorState.for(ractor)&.join values = ::Ractor.store_if_absent("Ractor#value") { ObjectSpace::WeakKeyMap.new } entry = values[ractor] ||= [Mutex.new] entry.first.synchronize { entry << ractor.take if entry.size == 1 } entry[1] end end end %i[alive? default_port join monitor unmonitor value].each do |method| next if respond_to?(method) class_eval <<~RUBY, __FILE__, __LINE__ + 1 def self.#{method}(ractor, ...) = ractor.#{method}(...) RUBY end unless respond_to?(:receive) def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) timeout.nil? ? ractor_or_port.receive : ractor_or_port.receive(timeout:) end end def self.select(...) = Farce::Ractor.select(...) # Installs the Farce backports for Ractor and Ractor::Port globally. def self.install Extension.install do if Internal.native_ractors? ::Ractor.const_set(:Port, Farce::Ractor::Port) unless Internal.native_ports? else Object.const_set(:Ractor, Farce::Ractor) end end end end |
.value(ractor) ⇒ Object
Backport for Ractor#value
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/farce/backports.rb', line 136 module Backports # @!visibility private Extension = Farce::Extension.new private_constant :Extension include Extension if Internal.native_ractors? if needs_timeouts = ::Ractor.instance_method(:receive).arity.zero? Extension.define(::Ractor) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end Extension.define(::Ractor.singleton_class) do def select(*sources, timeout: nil, **) # The selector helper must reach Ruby's native wait without reentering itself. return super(*sources, **) if timeout.nil? && (Internal.native_ports? || sources.all?(::Ractor)) Farce::Ractor.select(*sources, timeout:, **) end end def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) return ractor_or_port.receive if timeout.nil? return ractor_or_port.receive(timeout:) unless Internal.native_ports? Internal::RactorSelector.current.ractor_receive(ractor_or_port, timeout:) end end if Internal.native_ports? unless ::Ractor.method_defined?(:alive?) Extension.define(::Ractor) { def alive? = Backports.alive?(self) } def self.alive?(ractor) ractor.monitor(NULL_PORT) ensure ractor.unmonitor(NULL_PORT) end end if needs_timeouts Extension.define(::Ractor::Port) do def receive(timeout: nil) return super() if timeout.nil? Internal::RactorSelector.current.ractor_receive(self, timeout:) end end end else Extension.define(::Ractor) do def alive? = Backports.alive?(self) def default_port = Backports.default_port(self) def join = Backports.join(self) def monitor(port) = Backports.monitor(self, port) def unmonitor(port) = Backports.unmonitor(self, port) def value = Backports.value(self) end def self.alive?(ractor) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.alive? if state !ractor.inspect.end_with?("terminated>") end def self.default_port(ractor) = Farce::Ractor::Port.new(ractor) def self.join(ractor) Internal::RactorState.for(ractor)&.join ractor end def self.monitor(ractor, port) return true if Ractor.main == ractor state = Internal::RactorState.for(ractor) return state.monitor(port) if state raise Ractor::Error, "#{ractor.inspect} cannot be monitored" unless ractor.inspect.end_with?("terminated>") success = true begin ractor.take rescue Ractor::ClosedError # no-op rescue Ractor::RemoteError success = false end port.send(success ? :exited : :aborted) false end def self.unmonitor(ractor, port) Internal::RactorState.for(ractor)&.unmonitor(port) ractor end def self.value(ractor) Internal::RactorState.for(ractor)&.join values = ::Ractor.store_if_absent("Ractor#value") { ObjectSpace::WeakKeyMap.new } entry = values[ractor] ||= [Mutex.new] entry.first.synchronize { entry << ractor.take if entry.size == 1 } entry[1] end end end %i[alive? default_port join monitor unmonitor value].each do |method| next if respond_to?(method) class_eval <<~RUBY, __FILE__, __LINE__ + 1 def self.#{method}(ractor, ...) = ractor.#{method}(...) RUBY end unless respond_to?(:receive) def self.receive(ractor_or_port, timeout: nil) ractor_or_port = default_port(ractor_or_port) if ractor_or_port.is_a?(Ractor) timeout.nil? ? ractor_or_port.receive : ractor_or_port.receive(timeout:) end end def self.select(...) = Farce::Ractor.select(...) # Installs the Farce backports for Ractor and Ractor::Port globally. def self.install Extension.install do if Internal.native_ractors? ::Ractor.const_set(:Port, Farce::Ractor::Port) unless Internal.native_ports? else Object.const_set(:Ractor, Farce::Ractor) end end end end |