Class: ShadowLink
- Inherits:
-
Object
- Object
- ShadowLink
- Defined in:
- lib/shadow_link.rb,
lib/shadow_link/error.rb,
lib/shadow_link/mirror.rb,
lib/shadow_link/shadow.rb,
lib/shadow_link/version.rb
Overview
ShadowLink is a library that allows you to create a “shadow” of an object in a separate Ractor, enabling concurrent processing and communication between the original object and its shadow. It provides a way to offload work to a separate thread while maintaining a reference to the original object.
Defined Under Namespace
Constant Summary collapse
- DEFAULT_MAKE_SHAREABLES =
[String].freeze
- VERSION =
'0.1.0'
Class Method Summary collapse
- .lurk(*objects, threads: 1, make_shareables: DEFAULT_MAKE_SHAREABLES, &block) ⇒ Object
- .make_shareable?(object, make_shareables: DEFAULT_MAKE_SHAREABLES) ⇒ Boolean
Instance Method Summary collapse
-
#initialize(port, object_id, make_shareables:) ⇒ ShadowLink
constructor
A new instance of ShadowLink.
-
#method_missing(name, *args, **kwargs, &block) ⇒ Object
rubocop:disable Style/MissingRespondToMissing.
Constructor Details
#initialize(port, object_id, make_shareables:) ⇒ ShadowLink
Returns a new instance of ShadowLink.
12 13 14 15 16 17 |
# File 'lib/shadow_link.rb', line 12 def initialize(port, object_id, make_shareables:) @port = port @object_id = object_id @make_shareables = make_shareables freeze end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, **kwargs, &block) ⇒ Object
rubocop:disable Style/MissingRespondToMissing
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/shadow_link.rb', line 25 def method_missing(name, *args, **kwargs, &block) # rubocop:disable Style/MissingRespondToMissing process = lambda do |shadow = nil| if shadow args = args.map { |arg| shadow.sink(arg) } kwargs = kwargs.transform_values { |value| shadow.sink(value) } block = shadow.sink(block) if block end port = Ractor::Port.new @port.send({ object_id: @object_id, port:, name:, args:, kwargs:, block: }) case port.receive in { type: :success, value: } value in { type: :error, value: } raise ShadowLink::Error, value in raise "Unexpected message: #{.inspect}" end ensure port.close end convert = ->(value) { ShadowLink.make_shareable?(value, make_shareables: @make_shareables) ? Ractor.make_shareable(value) : value } args = args.map(&convert) kwargs = kwargs.transform_values(&convert) has_unshareable_args = [*args, *kwargs.values, block].any? { |arg| !Ractor.shareable?(arg) } has_unshareable_args ? ShadowLink.lurk(&process) : process.call end |
Class Method Details
.lurk(*objects, threads: 1, make_shareables: DEFAULT_MAKE_SHAREABLES, &block) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/shadow_link.rb', line 57 def lurk(*objects, threads: 1, make_shareables: DEFAULT_MAKE_SHAREABLES, &block) shadow = ShadowLink::Shadow.new(threads:, make_shareables:).start begin result = yield(*objects.map { |object| shadow.sink(object) }, shadow) result.is_a?(ShadowLink) ? shadow.seek(result) : result rescue Ractor::RemoteError => e raise (shadow.seek(e.cause.shadow) if e.cause.is_a?(ShadowLink::Error)) || e rescue ShadowLink::Error => e raise shadow.seek(e.shadow) || e ensure shadow.close end end |
.make_shareable?(object, make_shareables: DEFAULT_MAKE_SHAREABLES) ⇒ Boolean
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/shadow_link.rb', line 72 def make_shareable?(object, make_shareables: DEFAULT_MAKE_SHAREABLES) return false if Ractor.shareable?(object) case object when *make_shareables true else false end end |