robustthread 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/robustthread.rb +77 -41
  2. metadata +2 -2
data/lib/robustthread.rb CHANGED
@@ -1,68 +1,104 @@
1
- # This module allows for the creation of a thread that will not simply die when
2
- # the process dies. Instead, it joins all RobustThreads in Ruby's exit handler.
3
- #
4
1
  # Author:: Jared Kuolt (mailto:me@superjared.com)
5
2
  # Copyright:: Copyright (c) 2009 Jared Kuolt
6
3
  # License:: MIT License
4
+ #
5
+ # This module allows for the creation of a thread that will not simply die when
6
+ # the process dies. Instead, it joins all RobustThreads in Ruby's exit handler.
7
+ #
8
+ # Usage:
9
+ #
10
+ # rt = RobustThread.new(args) do |x, y|
11
+ # do_something(x, y)
12
+ # end
13
+ #
14
+ # If necessary, you can access the actual thread from the RobustThread
15
+ # object via its +thread+ attribute.
16
+ #
17
+ # rt.thread
18
+ # => #<Thread:0x7fa1ea57ff88 run>
19
+ #
20
+ # By default, RobustThread uses a Logger that defaults itself to STDOUT. You
21
+ # can change this by assigning the +logger+ class attribute to a different
22
+ # Logger object:
23
+ #
24
+ # RobustThread.logger = Logger.new(STDERR)
25
+ #
26
+ # Since Threads usually eat exceptions, RobustThread allows for a simple global
27
+ # exception handler:
28
+ #
29
+ # RobustThread.exception_handler do |exception|
30
+ # # Handle your exceptions here
31
+ # end
32
+ #
33
+ # If no handler is assigned, the exception traceback will be piped into the
34
+ # logger as an error message.
35
+ require 'logger'
7
36
 
8
37
  class RobustThread
9
38
  # The Thread object, brah
10
39
  attr_reader :thread
11
40
  # If the Thread takes a poopie...
12
41
  attr_reader :exception
13
- @@exit_handler_initialized = false
14
- @@exception_handler = nil
15
- # Usage:
16
- #
17
- # rt = RobustThread.new(args) do |x, y|
18
- # do_something(x, y)
19
- # end
20
- #
21
- # If necessary, you can access the actual thread from the +RobustThread+
22
- # object via its +thread+ attribute.
23
- #
24
- # rt.thread
25
- # => #<Thread:0x7fa1ea57ff88 run>
42
+
43
+ # Create a new RobustThread (see usage)
26
44
  def initialize(*args, &block)
27
- RobustThread.init_exit_handler
45
+ self.class.send :init_exit_handler
28
46
  @thread = Thread.new(*args) do |*targs|
29
47
  begin
30
48
  block.call(*targs)
31
49
  rescue => e
32
50
  @exception = e
33
- RobustThread.handle_exception(e)
51
+ self.class.send :handle_exception, e
34
52
  end
35
53
  end
36
54
  @thread[:real_ultimate_power] = true
37
55
  end
38
56
 
39
- # Set exception handler:
40
- #
41
- # RobustThread.exception_handler do |exception|
42
- # handle_exception(exception)
43
- # end
44
- def RobustThread.exception_handler(&block)
45
- unless block.arity == 1
46
- raise ArgumentError, "Bad arity for exception handler. It may only accept a single argument"
57
+ ## Class methods and attributes
58
+ class << self
59
+ attr_accessor :logger, :exit_handler_initialized
60
+
61
+ # Logger object (see usage)
62
+ def logger
63
+ @logger ||= Logger.new(STDOUT)
47
64
  end
48
- @@exception_handler = block
49
- end
50
65
 
51
- private
52
- # Sets up the exit_handler unless @@exit_handler_initialized
53
- def RobustThread.init_exit_handler
54
- return if @@exit_handler_initialized
55
- at_exit do
56
- Thread.list.each do |thread|
57
- thread.join if thread[:real_ultimate_power]
66
+ # Set exception handler
67
+ def exception_handler(&block)
68
+ unless block.arity == 1
69
+ raise ArgumentError, "Bad arity for exception handler. It may only accept a single argument"
70
+ end
71
+ @exception_handler = block
72
+ end
73
+
74
+ private
75
+ # Calls exception handler if set (see RobustThread.exception_handler)
76
+ def handle_exception(exc)
77
+ if @exception_handler.is_a? Proc
78
+ @exception_handler.call(exc)
79
+ else
80
+ self.logger.error("RobustThread: Unhandled exception:\n#{exc.message} " \
81
+ "(#{exc.class}): \n\t#{exc.backtrace.join("\n\t")}")
58
82
  end
59
83
  end
60
- @@exit_handler_initialized = true
61
- end
62
84
 
63
- # Calls exception handler if set (see RobustThread.exception_handler)
64
- def RobustThread.handle_exception(exception)
65
- return unless @@exception_handler
66
- @@exception_handler.call(exception)
85
+ # Sets up the exit_handler unless exit_handler_initialized
86
+ def init_exit_handler
87
+ return if self.exit_handler_initialized
88
+ at_exit do
89
+ begin
90
+ Thread.list.each do |thread|
91
+ if thread[:real_ultimate_power]
92
+ logger.info "RobustThread waiting on #{thread.inspect}"
93
+ thread.join
94
+ end
95
+ end
96
+ logger.info "RobustThread exited cleanly"
97
+ rescue Interrupt
98
+ logger.error "RobustThread(s) prematurely killed by interrupt!"
99
+ end
100
+ end
101
+ self.exit_handler_initialized = true
102
+ end
67
103
  end
68
104
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: robustthread
3
3
  version: !ruby/object:Gem::Version
4
- version: "0.2"
4
+ version: "0.3"
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jared Kuolt
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-03 00:00:00 -07:00
12
+ date: 2009-06-05 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15