Skip to content

Instantly share code, notes, and snippets.

@nevans
Last active August 24, 2022 18:27
Show Gist options
  • Save nevans/556234f6d709be9cd88ffcce2c1e9fdd to your computer and use it in GitHub Desktop.
Save nevans/556234f6d709be9cd88ffcce2c1e9fdd to your computer and use it in GitHub Desktop.
freezing procs
# frozen_string_literal: true
# requires ruby 3.1+
# Ractor.make_shareable(proc) only succeeds if everything on the proc's binding is shareable.
#
# This makes it difficult to create wrappers around Ractor.new that accept an arbitrary block.
# Even this would still require the block declare any outer variables as block-locals, even if
# they aren't used.
class ProcFreezer
def initialize = freeze
def call(&); Ractor.current.instance_exec(&) => Proc => p; p end # block must return a Proc
def make_shareable(&) = Ractor.make_shareable(call(&))
def self.ractor(*a, name: nil, &b)
f = new
b = f.make_shareable(&b)
i = f.make_shareable {->(a;name){ puts "inner? => %p" % [Ractor.current]; b.call(*a) }}
r = Ractor.new(a, i, name: name) do |a, i|
puts "init Ractor => %p" % Ractor.current
i.call(a)
end
end
end
ProcFreezer
.ractor do puts "make_shareable => %p" % [Ractor.current]; -> {:bar} end
.take
# >> make_shareable => #<Ractor:#1 running>
# >> init Ractor => #<Ractor:#11 (irb):218 running>
# >> inner? => #<Ractor:#11 (irb):218 running>
# => :bar
@nevans
Copy link
Author

nevans commented Aug 24, 2022

honestly though, I'm probably better off just using fiddle to FFI-cheat with rb_isolate_proc_bang

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment