class Backports::Ractor::Cloner
def clone_deeper(obj)
If no deep copy is needed, `obj` is returned and
Yields a deep copy.
def clone_deeper(obj) obj if Ractor.ractor_shareable_self?(obj, false) { false } = process(obj) do |r| _contents(r) obj unless result result if block_given?
def copy_contents(obj)
def copy_contents(obj) bj :Hash bj.default one_deeper(obj.default) do |copy| obj.default = copy d transform_keys! { |key| clone_deeper(key) } transform_values! { |value| clone_deeper(value) } :Array map! { |item| clone_deeper(item) } :Struct each_pair do |key, item| one_deeper(item) { |copy| obj[key] = copy } stance_variables.each do |var| e_deeper(obj.instance_variable_get(var)) do |copy| j.instance_variable_set(var, copy)
def deep_clone(obj)
def deep_clone(obj) return obj if Ractor.ractor_shareable_self?(obj, false) { false } new.deep_clone(obj) end
def deep_clone(obj)
def deep_clone(obj) result = process(obj) do |r| copy_contents(r) end return result if result Ractor.ractor_mark_set_shareable(@processed) obj end
def initialize
def initialize @processed = {}.compare_by_identity @changed = nil end
def process(obj)
Yields if `obj` is a new structure
def process(obj) ssed.fetch(obj) do r recursive structures, assume that we'll need a duplicate. that's not the case, we will have duplicated the whole structure r nothing... cessed[obj] = result = obj.dup ged = track_change { yield result } rn false if obj.frozen? && !changed nged = true lt.freeze if obj.frozen? lt
def track_change
def track_change @changed ed = false ed ed = prev