Class: Vli::Util::Busy

Inherits:
Object
  • Object
show all
Defined in:
lib/vli/util/busy.rb

Overview

Utility class which allows blocks of code to be marked as “busy” with a specified interrupt handler. During busy areas of code, it is often undesirable for SIGINTs to immediately kill the application. This class is a helper to cleanly register callbacks to handle this situation.

Constant Summary collapse

@@registered =
[]
@@mutex =
Mutex.new

Class Method Summary collapse

Class Method Details

.busy(sig_callback) ⇒ Object

Mark a given block of code as a “busy” block of code, which will register a SIGINT handler for the duration of the block. When a SIGINT occurs, the ‘sig_callback` proc will be called. It is up to the callback to behave properly and exit the application.



17
18
19
20
21
22
# File 'lib/vli/util/busy.rb', line 17

def busy(sig_callback)
  register(sig_callback)
  yield
ensure
  unregister(sig_callback)
end

.fire_callbacksObject

Fires all the registered callbacks.



48
49
50
# File 'lib/vli/util/busy.rb', line 48

def fire_callbacks
  registered.reverse.each { |r| r.call }
end

.register(sig_callback) ⇒ Object

Registers a SIGINT handler. This typically is called from busy. Callbacks are only registered once, so calling this multiple times with the same callback has no consequence.



27
28
29
30
31
32
33
34
35
# File 'lib/vli/util/busy.rb', line 27

def register(sig_callback)
  @@mutex.synchronize do
    registered << sig_callback
    registered.uniq!

    # Register the handler if this is our first callback.
    Signal.trap("INT") { fire_callbacks } if registered.length == 1
  end
end

.registeredObject

Helper method to get access to the class variable. This is mostly exposed for tests. This shouldn’t be mucked with directly, since it’s structure may change at any time.



55
# File 'lib/vli/util/busy.rb', line 55

def registered; @@registered; end

.unregister(sig_callback) ⇒ Object

Unregisters a SIGINT handler.



38
39
40
41
42
43
44
45
# File 'lib/vli/util/busy.rb', line 38

def unregister(sig_callback)
  @@mutex.synchronize do
    registered.delete(sig_callback)

    # Remove the signal trap if no more registered callbacks exist
    Signal.trap("INT", "DEFAULT") if registered.empty?
  end
end