Skip to content

Instantly share code, notes, and snippets.

@nevans
Last active August 24, 2022 18:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • 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

This solves a problem I'd been having: how to create a wrapper around Ractor.new. I want to initialize a ractor with some context vars, Tracepoint, etc, that the caller might not know or care about. Even if everthing is ractor sharable, it's still not trivial to fully isolate their proc.

I could probably remove some of the code here, but this was the first version I got working, so here it is. :)

@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