diff --git a/CHANGELOG.md b/CHANGELOG.md index b181f60..b251dbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +### Fixed +* Fix defining object finalizer in Ruby 3.1 to reference a UUID string + by Vadim Kononov(@vkononov) + ## [v0.14.0] - 2020-09-12 ### Added diff --git a/lib/finite_machine/observer.rb b/lib/finite_machine/observer.rb index 4591d57..ec31b2a 100644 --- a/lib/finite_machine/observer.rb +++ b/lib/finite_machine/observer.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "securerandom" + require_relative "async_call" require_relative "callable" require_relative "hook_event" @@ -13,20 +15,6 @@ module FiniteMachine class Observer < GenericDSL include Safety - # Clean up callback queue - # - # @api private - def self.cleanup_callback_queue - proc do - begin - if callback_queue.alive? - callback_queue.shutdown - end - rescue MessageQueueDeadError - end - end - end - # The current state machine attr_reader :machine @@ -44,11 +32,6 @@ def initialize(machine) @hooks = Hooks.new @machine.subscribe(self) - ObjectSpace.define_finalizer(self, self.class.cleanup_callback_queue) - end - - def callback_queue - @callback_queue ||= MessageQueue.new end # Evaluate in current context @@ -204,6 +187,35 @@ def defer(callable, trans_event, *data) callback_queue << async_call end + # Get an existing callback queue or create a new one + # + # @return [FiniteMachine::MessageQueue] + # + # @api private + def callback_queue + @callback_queue ||= MessageQueue.new.tap do + @queue_id = SecureRandom.uuid + ObjectSpace.define_finalizer(@queue_id, proc do + cleanup_callback_queue + end) + end + end + + # Clean up the callback queue + # + # @return [Boolean, nil] + # + # @api private + def cleanup_callback_queue + ObjectSpace.undefine_finalizer(@queue_id) if @queue_id + return unless @callback_queue && callback_queue.alive? + + begin + callback_queue.shutdown + rescue MessageQueueDeadError + end + end + # Create callable instance # # @api private