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

event_loop[R]
name[R]

Public Class Methods

new(name, thread, event_loop) click to toggle source
# 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

abort() click to toggle source

Send a AbortAction to the running thread.

# File lib/eventbox/boxable.rb, line 287
def abort
  @thread.raise AbortAction
end
current?() click to toggle source

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
join() click to toggle source

@private

# File lib/eventbox/boxable.rb, line 297
def join
  @thread.join
end
raise(*args) click to toggle source

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
terminate() click to toggle source

@private

# File lib/eventbox/boxable.rb, line 302
def terminate
  @thread.terminate
end