Class: Eventbox::Action

Inherits:
Object
  • Object
show all
Defined in:
lib/eventbox/boxable.rb

Overview

An Action object is thin wrapper for a Ruby thread.

It is returned by #action 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 AbortAction. It is raised by #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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, thread, event_loop) ⇒ Action

Returns a new instance of Action.



253
254
255
256
257
# File 'lib/eventbox/boxable.rb', line 253

def initialize(name, thread, event_loop)
  @name = name
  @thread = thread
  @event_loop = event_loop
end

Instance Attribute Details

#event_loopObject (readonly, private)

Returns the value of attribute event_loop.



259
260
261
# File 'lib/eventbox/boxable.rb', line 259

def event_loop
  @event_loop
end

#nameObject (readonly)

Returns the value of attribute name.



251
252
253
# File 'lib/eventbox/boxable.rb', line 251

def name
  @name
end

Instance Method Details

#abortObject

Send a AbortAction to the running thread.



284
285
286
# File 'lib/eventbox/boxable.rb', line 284

def abort
  @thread.raise AbortAction
end

#current?Boolean

Belongs the current thread to this action.

Returns:

  • (Boolean)


289
290
291
# File 'lib/eventbox/boxable.rb', line 289

def current?
  @thread.respond_to?(:current?) ? @thread.current? : (@thread == Thread.current)
end

#raise(*args) ⇒ Object

Send a signal to the running action.

The signal must be kind of Exception. See Eventbox::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`.



271
272
273
274
275
276
277
278
279
280
281
# File 'lib/eventbox/boxable.rb', line 271

def raise(*args)
  # ignore raise, if sent from the action thread
  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