class Eventbox::Action
An Action
object is thin wrapper for a Ruby thread.
It is returned by {Eventbox::Boxable#action action methods} and optionally passed as last argument to action methods. It can be used to interrupt the program execution by an exception.
However in contrast to ruby's builtin threads, any interruption must be explicit allowed. Exceptions raised to an action thread are delayed until a code block is reached which explicit allows interruption. The only exception which is delivered to the action thread by default is {Eventbox::AbortAction}. It is raised by {Eventbox#shutdown!} and is delivered as soon as a blocking operation is executed.
An Action
object can be used to stop the action while blocking operations. It should be made sure, that the rescue
statement is outside of the block to handle_interrupt
. Otherwise it could happen, that the rescuing code is interrupted by the signal. Sending custom signals to an action works like:
class MySignal < Interrupt end async_call def init a = start_sleep a.raise(MySignal) end action def start_sleep Thread.handle_interrupt(MySignal => :on_blocking) do sleep end rescue MySignal puts "well-rested" end
Attributes
Public Class Methods
# File lib/eventbox/boxable.rb, line 257 def initialize(name, thread, event_loop) @name = name @thread = thread @event_loop = event_loop end
Public Instance Methods
Send a AbortAction
to the running thread.
# File lib/eventbox/boxable.rb, line 287 def abort @thread.raise AbortAction end
Belongs the current thread to this action.
# File lib/eventbox/boxable.rb, line 292 def current? @thread.respond_to?(:current?) ? @thread.current? : (@thread == Thread.current) end
@private
# File lib/eventbox/boxable.rb, line 297 def join @thread.join end
Send a signal to the running action.
The signal must be kind of Exception. See {Action} about asynchronous delivery of signals.
This method does nothing if the action is already finished.
If {raise} is called within the action ({#current?} returns true
), all exceptions are delivered immediately. This happens regardless of the current interrupt mask set by Thread.handle_interrupt
.
# File lib/eventbox/boxable.rb, line 275 def raise(*args) if AbortAction === args[0] || (Module === args[0] && args[0].ancestors.include?(AbortAction)) ::Kernel.raise InvalidAccess, "Use of Eventbox::AbortAction is not allowed - use Action#abort or a custom exception subclass" end if @event_loop.event_scope? args = Sanitizer.sanitize_values(args, @event_loop, nil) end @thread.raise(*args) end
@private
# File lib/eventbox/boxable.rb, line 302 def terminate @thread.terminate end