lib/finite_machine/observer.rb in finite_machine-0.14.0 vs lib/finite_machine/observer.rb in finite_machine-0.14.1
- old
+ new
@@ -1,7 +1,9 @@
# frozen_string_literal: true
+require "securerandom"
+
require_relative "async_call"
require_relative "callable"
require_relative "hook_event"
require_relative "hooks"
require_relative "message_queue"
@@ -11,24 +13,10 @@
module FiniteMachine
# A class responsible for observing state changes
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
# The hooks to trigger around the transition lifecycle.
attr_reader :hooks
@@ -42,17 +30,12 @@
def initialize(machine)
@machine = 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
#
# @api private
def call(&block)
instance_eval(&block)
@@ -200,9 +183,38 @@
# @api private
def defer(callable, trans_event, *data)
async_call = AsyncCall.new(machine, callable, trans_event, *data)
callback_queue.start unless callback_queue.running?
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