diff --git a/src/fiber.cr b/src/fiber.cr index b34a8762037d..b27c34fd6b36 100644 --- a/src/fiber.cr +++ b/src/fiber.cr @@ -162,6 +162,10 @@ class Fiber @timeout_event.try &.free @timeout_select_action = nil + # Additional cleanup (avoid stale references) + @exec_recursive_hash = nil + @exec_recursive_clone_hash = nil + @alive = false {% unless flag?(:interpreted) %} Crystal::Scheduler.stack_pool.release(@stack) @@ -331,4 +335,18 @@ class Fiber @current_thread.lazy_get end {% end %} + + # :nodoc: + # + # See `Reference#exec_recursive` for details. + def exec_recursive_hash + @exec_recursive_hash ||= Hash({UInt64, Symbol}, Nil).new + end + + # :nodoc: + # + # See `Reference#exec_recursive_clone` for details. + def exec_recursive_clone_hash + @exec_recursive_clone_hash ||= Hash(UInt64, UInt64).new + end end diff --git a/src/reference.cr b/src/reference.cr index f70697282fa0..42bdcba2327a 100644 --- a/src/reference.cr +++ b/src/reference.cr @@ -1,7 +1,3 @@ -{% if flag?(:preview_mt) %} - require "crystal/thread_local_value" -{% end %} - # `Reference` is the base class of classes you define in your program. # It is set as a class' superclass when you don't specify one: # @@ -180,28 +176,9 @@ class Reference io << '>' end - # :nodoc: - module ExecRecursive - # NOTE: can't use `Set` here because of prelude require order - alias Registry = Hash({UInt64, Symbol}, Nil) - - {% if flag?(:preview_mt) %} - @@exec_recursive = Crystal::ThreadLocalValue(Registry).new - {% else %} - @@exec_recursive = Registry.new - {% end %} - - def self.hash - {% if flag?(:preview_mt) %} - @@exec_recursive.get { Registry.new } - {% else %} - @@exec_recursive - {% end %} - end - end - private def exec_recursive(method, &) - hash = ExecRecursive.hash + # NOTE: can't use `Set` because of prelude require order + hash = Fiber.current.exec_recursive_hash key = {object_id, method} hash.put(key, nil) do yield @@ -211,25 +188,6 @@ class Reference false end - # :nodoc: - module ExecRecursiveClone - alias Registry = Hash(UInt64, UInt64) - - {% if flag?(:preview_mt) %} - @@exec_recursive = Crystal::ThreadLocalValue(Registry).new - {% else %} - @@exec_recursive = Registry.new - {% end %} - - def self.hash - {% if flag?(:preview_mt) %} - @@exec_recursive.get { Registry.new } - {% else %} - @@exec_recursive - {% end %} - end - end - # Helper method to perform clone by also checking recursiveness. # When clone is wanted, call this method. Then create the clone # instance without any contents (don't fill it out yet), then @@ -249,7 +207,8 @@ class Reference # end # ``` private def exec_recursive_clone(&) - hash = ExecRecursiveClone.hash + # NOTE: can't use `Set` because of prelude require order + hash = Fiber.current.exec_recursive_clone_hash clone_object_id = hash[object_id]? unless clone_object_id clone_object_id = yield(hash).object_id