robustthread 0.3 → 0.4

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 +41 -45
  2. metadata +2 -2
data/lib/robustthread.rb CHANGED
@@ -1,37 +1,6 @@
1
1
  # Author:: Jared Kuolt (mailto:me@superjared.com)
2
2
  # Copyright:: Copyright (c) 2009 Jared Kuolt
3
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
4
  require 'logger'
36
5
 
37
6
  class RobustThread
@@ -39,10 +8,13 @@ class RobustThread
39
8
  attr_reader :thread
40
9
  # If the Thread takes a poopie...
41
10
  attr_reader :exception
11
+ # An identifier
12
+ attr_accessor :label
42
13
 
43
- # Create a new RobustThread (see usage)
44
- def initialize(*args, &block)
14
+ # Create a new RobustThread (see README)
15
+ def initialize(opts={}, &block)
45
16
  self.class.send :init_exit_handler
17
+ args = opts[:args] or []
46
18
  @thread = Thread.new(*args) do |*targs|
47
19
  begin
48
20
  block.call(*targs)
@@ -50,19 +22,43 @@ class RobustThread
50
22
  @exception = e
51
23
  self.class.send :handle_exception, e
52
24
  end
25
+ self.class.log "#{self.label.inspect} exited cleanly"
53
26
  end
54
- @thread[:real_ultimate_power] = true
27
+ self.label = opts[:label] || @thread.inspect
28
+ self.class.group << self
55
29
  end
56
30
 
57
31
  ## Class methods and attributes
58
32
  class << self
59
- attr_accessor :logger, :exit_handler_initialized
33
+ attr_accessor :logger, :say_goodnight, :exit_handler_initialized
60
34
 
61
- # Logger object (see usage)
35
+ # Logger object (see README)
62
36
  def logger
63
37
  @logger ||= Logger.new(STDOUT)
64
38
  end
65
39
 
40
+ # Simple log interface
41
+ def log(msg, level=:info)
42
+ self.logger.send level, "#{self}: " + msg
43
+ end
44
+
45
+ # The collection of RobustThread objects
46
+ def group
47
+ @group ||= []
48
+ end
49
+
50
+ # Loop an activity and exit it cleanly (see README)
51
+ def loop(opts={}, &block)
52
+ sleep_seconds = opts.delete(:seconds) || 2
53
+ self.new(opts) do |*args|
54
+ Kernel.loop do
55
+ break if self.say_goodnight
56
+ block.call(*args)
57
+ sleep sleep_seconds
58
+ end
59
+ end
60
+ end
61
+
66
62
  # Set exception handler
67
63
  def exception_handler(&block)
68
64
  unless block.arity == 1
@@ -77,25 +73,25 @@ class RobustThread
77
73
  if @exception_handler.is_a? Proc
78
74
  @exception_handler.call(exc)
79
75
  else
80
- self.logger.error("RobustThread: Unhandled exception:\n#{exc.message} " \
81
- "(#{exc.class}): \n\t#{exc.backtrace.join("\n\t")}")
76
+ log("Unhandled exception:\n#{exc.message} " \
77
+ "(#{exc.class}): \n\t#{exc.backtrace.join("\n\t")}", :error)
82
78
  end
83
79
  end
84
80
 
85
81
  # Sets up the exit_handler unless exit_handler_initialized
86
82
  def init_exit_handler
87
83
  return if self.exit_handler_initialized
84
+ self.say_goodnight = false
88
85
  at_exit do
86
+ self.say_goodnight = true
89
87
  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
88
+ self.group.each do |rt|
89
+ log "waiting on #{rt.label.inspect}"
90
+ rt.thread.join
95
91
  end
96
- logger.info "RobustThread exited cleanly"
92
+ log "exited cleanly"
97
93
  rescue Interrupt
98
- logger.error "RobustThread(s) prematurely killed by interrupt!"
94
+ log "prematurely killed by interrupt!", :error
99
95
  end
100
96
  end
101
97
  self.exit_handler_initialized = true
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.3"
4
+ version: "0.4"
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-05 00:00:00 -07:00
12
+ date: 2009-06-08 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15