servolux 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,6 +1,12 @@
1
+ == 0.6.0 / 2009-07-07
2
+
3
+ * 2 Minor Enhancements
4
+ * Threaded objects can be set to run only a given number of times
5
+ * Threaded objects can now continue on error
6
+
1
7
  == 0.5.0 / 2009-06-30
2
8
 
3
- * 2 Minor Enchancements
9
+ * 2 Minor Enhancements
4
10
  * Added tests for the Child class
5
11
  * Updating documentation in preperation for a release
6
12
 
@@ -57,17 +57,28 @@ module Servolux::Threaded
57
57
 
58
58
  before_starting if self.respond_to?(:before_starting)
59
59
  @activity_thread_running = true
60
+ @activity_thread_iterations = 0
60
61
  @activity_thread = Thread.new {
61
62
  begin
62
63
  loop {
63
- sleep interval if running?
64
- break unless running?
65
- run
64
+ begin
65
+ sleep interval if running?
66
+ break unless running?
67
+ run
68
+ @activity_thread_iterations += 1
69
+ break if finished_iterations?
70
+ rescue SystemExit; raise
71
+ rescue Exception => err
72
+ if continue_on_error?
73
+ logger.error err
74
+ else
75
+ logger.fatal err
76
+ raise err
77
+ end
78
+ end
66
79
  }
67
- rescue Exception => err
80
+ ensure
68
81
  @activity_thread_running = false
69
- logger.fatal err unless err.is_a?(SystemExit)
70
- raise err
71
82
  end
72
83
  }
73
84
  after_starting if self.respond_to?(:after_starting)
@@ -96,6 +107,20 @@ module Servolux::Threaded
96
107
  self
97
108
  end
98
109
 
110
+ # Wait on the activity thread. If the thread is already stopped, this
111
+ # method will return without taking any action. Otherwise, this method
112
+ # does not return until the activity thread has stopped, or a specific
113
+ # number of iterations has passed since this method was called.
114
+ #
115
+ def wait( limit = nil )
116
+ return self unless running?
117
+ start_waiting_iterations = self.iterations
118
+ loop {
119
+ break unless running?
120
+ break if limit and self.iterations > ( start_waiting_iterations + limit )
121
+ }
122
+ end
123
+
99
124
  # If the activity thread is running, the calling thread will suspend
100
125
  # execution and run the activity thread. This method does not return until
101
126
  # the activity thread is stopped or until _limit_ seconds have passed.
@@ -115,6 +140,16 @@ module Servolux::Threaded
115
140
  @activity_thread_running
116
141
  end
117
142
 
143
+ # Returns +true+ if the activity thread has finished its maximum
144
+ # number of iterations or the thread is no longer running.
145
+ # Returns +false+ otherwise.
146
+ #
147
+ def finished_iterations?
148
+ return true unless running?
149
+ return true if maximum_iterations and (iterations >= maximum_iterations)
150
+ return false
151
+ end
152
+
118
153
  # Returns the status of threaded object.
119
154
  #
120
155
  # 'sleep' : sleeping or waiting on I/O
@@ -142,7 +177,50 @@ module Servolux::Threaded
142
177
  # threaded object's 'run' method.
143
178
  #
144
179
  def interval
145
- @activity_thread_interval
180
+ @activity_thread_interval ||= 60
181
+ end
182
+
183
+ # Sets the maximum number of invocations of the threaded object's
184
+ # 'run' method
185
+ #
186
+ def maximum_iterations=( value )
187
+ raise ArgumentError, "maximum iterations must be >= 1" unless value.to_i >= 1
188
+ @activity_thread_maximum_iterations = value.to_i
189
+ end
190
+
191
+ # Returns the maximum number of invocations of the threaded
192
+ # object's 'run' method
193
+ #
194
+ def maximum_iterations
195
+ return unless defined? @activity_thread_maximum_iterations
196
+ @activity_thread_maximum_iterations
197
+ end
198
+
199
+ # Returns the number of iterations of the threaded object's 'run' method
200
+ # completed thus far.
201
+ #
202
+ def iterations
203
+ @activity_thread_iterations ||= 0
204
+ end
205
+
206
+ # Set to +true+ to continue running the threaded object even if an error
207
+ # is raised by the +run+ method. The default behavior is to stop the
208
+ # activity thread when an error is raised by the run method.
209
+ #
210
+ # A SystemExit will never be caught; it will always cause the Ruby
211
+ # interpreter to exit.
212
+ #
213
+ def continue_on_error=( value )
214
+ @activity_thread_continue_on_error = (value ? true : false)
215
+ end
216
+
217
+ # Returns +true+ if the threded object should continue running even if an
218
+ # error is raised by the run method. The default is to return +false+. The
219
+ # threaded object will stop running when an error is raised.
220
+ #
221
+ def continue_on_error?
222
+ return @activity_thread_continue_on_error if defined? @activity_thread_continue_on_error
223
+ @activity_thread_continue_on_error = false
146
224
  end
147
225
 
148
226
  # :stopdoc:
data/lib/servolux.rb CHANGED
@@ -4,7 +4,7 @@ require 'logging'
4
4
  module Servolux
5
5
 
6
6
  # :stopdoc:
7
- VERSION = '0.5.0'
7
+ VERSION = '0.6.0'
8
8
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
9
9
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
10
10
  # :startdoc:
@@ -90,6 +90,32 @@ describe Servolux::Threaded do
90
90
  lambda { obj.join }.should raise_error(RuntimeError, 'ni')
91
91
  end
92
92
 
93
+ it "lives if told to continue on error" do
94
+ klass = Class.new(base) do
95
+ def run()
96
+ @sleep ||= false
97
+ if @sleep then sleep
98
+ else
99
+ @sleep = true
100
+ raise 'ni'
101
+ end
102
+ end
103
+ end
104
+
105
+ obj = klass.new
106
+ obj.continue_on_error = true
107
+
108
+ obj.start
109
+ obj.pass
110
+
111
+ obj.running?.should be_true
112
+ @log_output.readline
113
+ @log_output.readline.chomp.should == "ERROR Object : <RuntimeError> ni"
114
+
115
+ obj.stop(2)
116
+ obj.running?.should be_false
117
+ end
118
+
93
119
  it "complains loudly if you don't have a run method" do
94
120
  obj = base.new
95
121
  obj.start
@@ -100,6 +126,23 @@ describe Servolux::Threaded do
100
126
 
101
127
  lambda { obj.join }.should raise_error(NotImplementedError, 'The run method must be defined by the threaded object.')
102
128
  end
129
+
130
+ it "stops after a limited number of iterations" do
131
+ klass = Class.new( base ) do
132
+ def run() ; end
133
+ end
134
+ obj = klass.new
135
+ obj.maximum_iterations = 5
136
+ obj.iterations.should == 0
137
+ obj.start
138
+ obj.wait
139
+ obj.iterations.should == 5
140
+ end
141
+
142
+ it "complains loudly if you attempt to set a maximum number of iterations < 1" do
143
+ obj = base.new
144
+ lambda { obj.maximum_iterations = -1 }.should raise_error( ArgumentError, "maximum iterations must be >= 1" )
145
+ end
103
146
  end
104
147
 
105
148
  # EOF
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: servolux
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Pease
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-30 00:00:00 -06:00
12
+ date: 2009-07-07 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency