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 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 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.



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

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.



263
264
265
# File 'lib/eventbox/boxable.rb', line 263

def event_loop
  @event_loop
end

#nameObject (readonly)

Returns the value of attribute name.



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

def name
  @name
end

Instance Method Details

#abortObject

Send a AbortAction to the running thread.



287
288
289
# File 'lib/eventbox/boxable.rb', line 287

def abort
  @thread.raise AbortAction
end

#current?Boolean

Belongs the current thread to this action.

Returns:

  • (Boolean)


292
293
294
# File 'lib/eventbox/boxable.rb', line 292

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.



275
276
277
278
279
280
281
282
283
284
# 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