delayer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in delayer.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Toshiaki Asai
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,39 @@
1
+ # Delayer
2
+
3
+ Delay Any task. Similar priority-queue.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'delayer'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install delayer
18
+
19
+ ## Usage
20
+
21
+ Task = Delayer.generate_class # Define basic class
22
+ Task = Delayer.generate_class(priority: [:high, :middle, :low], default: :middle) # or, Priority delayer
23
+ Task = Delayer.generate_class(expire: 0.5) # and/or, Time limited delayer.
24
+
25
+ task = Task.new { delayed code ... } # Register task
26
+ task = Task.new(:high) { delayed code ... } # or, You can specify priority.
27
+
28
+ task.cancel # Task can cancel before Delayer#run.
29
+
30
+ Task.run # Execute all tasks.
31
+ Task.run(1) # or, You can specify expire.
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create new Pull Request
@@ -0,0 +1,13 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ task :default => [:test]
6
+
7
+ Rake::TestTask.new do |test|
8
+ # $LOAD_PATH に追加するパス (デフォルトで 'lib' は入っている)
9
+ test.libs << 'test'
10
+ # テスト対象ファイルの指定
11
+ test.test_files = Dir[ 'test/**/test_*.rb' ]
12
+ test.verbose = true
13
+ end
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'delayer/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "delayer"
8
+ spec.version = Delayer::VERSION
9
+ spec.authors = ["Toshiaki Asai"]
10
+ spec.email = ["toshi.alternative@gmail.com"]
11
+ spec.description = %q{Delay the processing}
12
+ spec.summary = %q{Delay the processing}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.2.3"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,61 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "delayer/version"
3
+ require "delayer/error"
4
+ require "delayer/extend"
5
+ require "delayer/procedure"
6
+ require "delayer/priority"
7
+ require "monitor"
8
+
9
+ module Delayer
10
+ class << self
11
+ attr_accessor :default
12
+
13
+ def included(klass)
14
+ klass.extend Extend
15
+ end
16
+
17
+ # Generate new Delayer class.
18
+ # ==== Args
19
+ # [options]
20
+ # Hash
21
+ # expire :: processing expire (secs, 0=unlimited)
22
+ # priority :: priorities
23
+ # default :: default priotity
24
+ # ==== Return
25
+ # A new class
26
+ def generate_class(options = {})
27
+ if options[:priority]
28
+ Class.new do
29
+ include Priority
30
+ @expire = options[:expire] || 0
31
+ @priorities = options[:priority]
32
+ @default_priority = options[:default]
33
+ end
34
+ else
35
+ Class.new do
36
+ include ::Delayer
37
+ @expire = options[:expire] || 0
38
+ end
39
+ end
40
+ end
41
+
42
+ def method_missing(*args, &proc)
43
+ (@default ||= generate_class).__send__(*args, &proc)
44
+ end
45
+ end
46
+
47
+ def initialize(*args)
48
+ super
49
+ @procedure = Procedure.new(self, &Proc.new)
50
+ end
51
+
52
+ # Cancel this job
53
+ # ==== Exception
54
+ # Delayer::AlreadyExecutedError :: if already called run()
55
+ # ==== Return
56
+ # self
57
+ def cancel
58
+ @procedure.cancel
59
+ self
60
+ end
61
+ end
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Delayer
4
+ class Error < ::StandardError; end
5
+ class TooLate < Error; end
6
+ class AlreadyExecutedError < TooLate; end
7
+ class AlreadyCanceledError < TooLate; end
8
+ class AlreadyRunningError < TooLate; end
9
+ class InvalidPriorityError < Error; end
10
+ def self.StateError(state)
11
+ case state
12
+ when :run
13
+ AlreadyRunningError
14
+ when :done
15
+ AlreadyExecutedError
16
+ when :cancel
17
+ AlreadyCanceledError
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,126 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Delayer
4
+ module Extend
5
+ attr_accessor :expire
6
+
7
+ def self.extended(klass)
8
+ klass.class_eval do
9
+ @first_pointer = @last_pointer = nil
10
+ @busy = false
11
+ @expire = 0
12
+ @remain_hook = nil
13
+ @remain_received = false
14
+ @lock = Mutex.new
15
+ end
16
+ end
17
+
18
+ # Run registered jobs.
19
+ # ==== Args
20
+ # [current_expire] expire for processing (secs, 0=unexpired)
21
+ # ==== Return
22
+ # self
23
+ def run(current_expire = @expire)
24
+ if 0 == current_expire
25
+ run_once while not empty?
26
+ else
27
+ @end_time = Time.new.to_f + @expire
28
+ run_once while not(empty?) and @end_time >= Time.new.to_f
29
+ @end_time = nil
30
+ end
31
+ if @remain_hook
32
+ @remain_received = !empty?
33
+ @remain_hook.call if @remain_received
34
+ end
35
+ end
36
+
37
+ def expire?
38
+ if defined?(@end_time) and @end_time
39
+ @end_time < Time.new.to_f
40
+ else
41
+ false
42
+ end
43
+ end
44
+
45
+ # Run a job and forward pointer.
46
+ # ==== Return
47
+ # self
48
+ def run_once
49
+ if @first_pointer
50
+ @busy = true
51
+ procedure = forward
52
+ procedure = forward while @first_pointer and procedure.canceled?
53
+ procedure.run unless procedure.canceled?
54
+ end
55
+ ensure
56
+ @busy = false
57
+ end
58
+
59
+ # Return if some jobs processing now.
60
+ # ==== Args
61
+ # [args]
62
+ # ==== Return
63
+ # true if Delayer processing job
64
+ def busy?
65
+ @busy
66
+ end
67
+
68
+ # Return true if no jobs has.
69
+ # ==== Return
70
+ # true if no jobs has.
71
+ def empty?
72
+ !@first_pointer
73
+ end
74
+
75
+ # Return remain jobs quantity.
76
+ # ==== Return
77
+ # Count of remain jobs
78
+ def size(node = @first_pointer)
79
+ if node
80
+ 1 + size(node.next)
81
+ else
82
+ 0
83
+ end
84
+ end
85
+
86
+ # register new job.
87
+ # ==== Args
88
+ # [procedure] job(Delayer::Procedure)
89
+ # ==== Return
90
+ # self
91
+ def register(procedure)
92
+ lock.synchronize do
93
+ if @last_pointer
94
+ @last_pointer = @last_pointer.break procedure
95
+ else
96
+ @last_pointer = @first_pointer = procedure
97
+ end
98
+ if @remain_hook and not @remain_received
99
+ @remain_received = true
100
+ @remain_hook.call
101
+ end
102
+ end
103
+ self
104
+ end
105
+
106
+ def register_remain_hook
107
+ @remain_hook = Proc.new
108
+ end
109
+
110
+ private
111
+
112
+ def forward
113
+ lock.synchronize do
114
+ prev = @first_pointer
115
+ @first_pointer = @first_pointer.next
116
+ @last_pointer = nil unless @first_pointer
117
+ prev
118
+ end
119
+ end
120
+
121
+ def lock
122
+ @lock
123
+ end
124
+
125
+ end
126
+ end
@@ -0,0 +1,84 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Delayer
4
+ module Priority
5
+ attr_reader :priority
6
+
7
+ def self.included(klass)
8
+ klass.class_eval do
9
+ include ::Delayer
10
+ extend Extend
11
+ end
12
+ end
13
+
14
+ def initialize(priority = self.class.instance_eval{ @default_priority }, *args)
15
+ self.class.validate_priority priority
16
+ @priority = priority
17
+ super(*args)
18
+ end
19
+
20
+ module Extend
21
+ def self.extended(klass)
22
+ klass.class_eval do
23
+ @priority_pointer = {}
24
+ end
25
+ end
26
+
27
+ # register new job.
28
+ # ==== Args
29
+ # [procedure] job(Delayer::Procedure)
30
+ # ==== Return
31
+ # self
32
+ def register(procedure)
33
+ priority = procedure.delayer.priority
34
+ lock.synchronize do
35
+ last_pointer = get_prev_point(priority)
36
+ if last_pointer
37
+ @priority_pointer[priority] = last_pointer.break procedure
38
+ else
39
+ procedure.next = @first_pointer
40
+ @priority_pointer[priority] = @first_pointer = procedure
41
+ end
42
+ if @last_pointer
43
+ @last_pointer = @priority_pointer[priority]
44
+ end
45
+ if @remain_hook and not @remain_received
46
+ @remain_received = true
47
+ @remain_hook.call
48
+ end
49
+ end
50
+ self
51
+ end
52
+
53
+ def get_prev_point(priority)
54
+ if @priority_pointer[priority]
55
+ @priority_pointer[priority]
56
+ else
57
+ next_index = @priorities.index(priority) - 1
58
+ get_prev_point @priorities[next_index] if 0 <= next_index
59
+ end
60
+ end
61
+
62
+ def validate_priority(symbol)
63
+ unless @priorities.include? symbol
64
+ raise Delayer::InvalidPriorityError, "undefined priority '#{symbol}'"
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def forward
71
+ lock.synchronize do
72
+ prev = @first_pointer
73
+ @first_pointer = @first_pointer.next
74
+ @last_pointer = nil unless @first_pointer
75
+ @priority_pointer.each do |priority, pointer|
76
+ @priority_pointer[priority] = @first_pointer if prev == pointer
77
+ end
78
+ prev
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,61 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Delayer
4
+ class Procedure
5
+ attr_reader :state, :delayer
6
+ attr_accessor :next
7
+ def initialize(delayer, &proc)
8
+ @delayer, @proc = delayer, proc
9
+ @state = :stop
10
+ @next = nil
11
+ @delayer.class.register(self)
12
+ end
13
+
14
+ # Run a process
15
+ # ==== Exception
16
+ # Delayer::TooLate :: if already called run()
17
+ # ==== Return
18
+ # node
19
+ def run
20
+ unless :stop == @state
21
+ raise Delayer::StateError(@state), "call twice Delayer::Procedure"
22
+ end
23
+ @state = :run
24
+ @proc.call
25
+ @state = :done
26
+ @proc = nil
27
+ end
28
+
29
+ # Cancel this job
30
+ # ==== Exception
31
+ # Delayer::TooLate :: if already called run()
32
+ # ==== Return
33
+ # self
34
+ def cancel
35
+ unless :stop == @state
36
+ raise Delayer::StateError(@state), "cannot cancel Delayer::Procedure"
37
+ end
38
+ @state = :cancel
39
+ self
40
+ end
41
+
42
+ # Return true if canceled this task
43
+ # ==== Return
44
+ # true if canceled this task
45
+ def canceled?
46
+ :cancel == @state
47
+ end
48
+
49
+ # insert node between self and self.next
50
+ # ==== Args
51
+ # [node] insertion
52
+ # ==== Return
53
+ # node
54
+ def break(node)
55
+ tail = @next
56
+ @next = node
57
+ node.next = tail
58
+ node
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,3 @@
1
+ module Delayer
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,317 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'test/unit'
6
+ require 'delayer'
7
+
8
+ class TestDelayer < Test::Unit::TestCase
9
+ def setup
10
+ Delayer.default = nil
11
+ end
12
+
13
+ def test_delayed
14
+ delayer = Delayer.generate_class
15
+ a = 0
16
+ delayer.new { a = 1 }
17
+
18
+ assert_equal(0, a)
19
+ delayer.run
20
+ assert_equal(1, a)
21
+ end
22
+
23
+ def test_default
24
+ a = 0
25
+ Delayer.new { a = 1 }
26
+
27
+ assert_equal(0, a)
28
+ Delayer.run
29
+ assert_equal(1, a)
30
+ end
31
+
32
+ def test_timelimited
33
+ delayer = Delayer.generate_class(expire: 0.01)
34
+ a = 0
35
+ delayer.new { sleep 0.1 }
36
+ delayer.new { a = 1 }
37
+
38
+ assert_equal(0, a)
39
+ delayer.run
40
+ assert_equal(0, a)
41
+ delayer.run
42
+ assert_equal(1, a)
43
+ end
44
+
45
+ def test_busy
46
+ delayer = Delayer.generate_class
47
+ a = false
48
+ delayer.new { a = delayer.busy? }
49
+
50
+ assert_equal(false, a)
51
+ assert_equal(false, delayer.busy?)
52
+ delayer.run
53
+ assert_equal(false, delayer.busy?)
54
+ assert_equal(true, a)
55
+ end
56
+
57
+ def test_empty
58
+ delayer = Delayer.generate_class
59
+ a = false
60
+ delayer.new { a = delayer.empty? }
61
+
62
+ assert_equal(false, a)
63
+ assert_equal(false, delayer.empty?)
64
+ delayer.run
65
+ assert_equal(true, delayer.empty?)
66
+ assert_equal(true, a)
67
+ end
68
+
69
+ def test_size
70
+ delayer = Delayer.generate_class
71
+ a = 0
72
+ assert_equal(0, delayer.size)
73
+ delayer.new { a += 1 }
74
+ assert_equal(1, delayer.size)
75
+ delayer.new { a += 1 }
76
+ delayer.new { a += 1 }
77
+ assert_equal(3, delayer.size)
78
+ delayer.run
79
+ assert_equal(0, delayer.size)
80
+ end
81
+
82
+ def test_cancel_begin
83
+ delayer = Delayer.generate_class
84
+ a = 0
85
+ d = delayer.new { a += 1 }
86
+ delayer.new { a += 2 }
87
+ delayer.new { a += 4 }
88
+
89
+ assert_equal(0, a)
90
+ d.cancel
91
+ delayer.run
92
+ assert_equal(6, a)
93
+ end
94
+
95
+ def test_cancel_center
96
+ delayer = Delayer.generate_class
97
+ a = 0
98
+ delayer.new { a += 1 }
99
+ d = delayer.new { a += 2 }
100
+ delayer.new { a += 4 }
101
+
102
+ assert_equal(0, a)
103
+ d.cancel
104
+ delayer.run
105
+ assert_equal(5, a)
106
+ end
107
+
108
+ def test_cancel_end
109
+ delayer = Delayer.generate_class
110
+ a = 0
111
+ delayer.new { a += 1 }
112
+ delayer.new { a += 2 }
113
+ d = delayer.new { a += 4 }
114
+
115
+ assert_equal(0, a)
116
+ d.cancel
117
+ delayer.run
118
+ assert_equal(3, a)
119
+ end
120
+
121
+ def test_priority_asc
122
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
123
+ default: :middle)
124
+ buffer = []
125
+ delayer.new(:high) { buffer << 1 }
126
+ delayer.new(:middle) { buffer << 2 }
127
+ delayer.new(:low) { buffer << 3 }
128
+ delayer.run
129
+ assert_equal([1,2,3], buffer)
130
+ end
131
+
132
+ def test_priority_desc
133
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
134
+ default: :middle)
135
+ buffer = []
136
+ delayer.new(:low) { buffer << 3 }
137
+ delayer.new(:middle) { buffer << 2 }
138
+ delayer.new(:high) { buffer << 1 }
139
+ delayer.run
140
+ assert_equal([1,2,3], buffer)
141
+ end
142
+
143
+ def test_priority_complex
144
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
145
+ default: :middle)
146
+ buffer = []
147
+ delayer.new(:high) { buffer << 1 }
148
+ delayer.new(:middle) { buffer << 2 }
149
+ delayer.new(:low) { buffer << 3 }
150
+ delayer.new(:middle) { buffer << 4 }
151
+ delayer.new(:high) { buffer << 5 }
152
+ delayer.new(:middle) { buffer << 6 }
153
+ delayer.new(:low) { buffer << 7 }
154
+ delayer.new(:middle) { buffer << 8 }
155
+ delayer.new(:high) { buffer << 9 }
156
+ delayer.run
157
+ assert_equal([1,5,9,2,4,6,8,3,7], buffer)
158
+
159
+ buffer = []
160
+ delayer.new(:high) { buffer << 1 }
161
+ delayer.new(:low) { buffer << 2 }
162
+ delayer.new(:high) { buffer << 3 }
163
+ delayer.new(:low) { buffer << 4 }
164
+ delayer.run
165
+ assert_equal([1,3,2,4], buffer)
166
+ end
167
+
168
+ def test_priority_cancel_begin
169
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
170
+ default: :middle)
171
+ a = 0
172
+ d = delayer.new { a += 1 }
173
+ delayer.new { a += 2 }
174
+ delayer.new { a += 4 }
175
+ assert_equal(0, a)
176
+ d.cancel
177
+ delayer.run
178
+ assert_equal(6, a)
179
+
180
+ a = 0
181
+ d = delayer.new(:low) { a += 1 }
182
+ delayer.new(:high) { a += 2 }
183
+ delayer.new(:high) { a += 4 }
184
+ assert_equal(0, a)
185
+ d.cancel
186
+ delayer.run
187
+ assert_equal(6, a)
188
+
189
+ a = 0
190
+ d = delayer.new(:high) { a += 1 }
191
+ delayer.new(:low) { a += 2 }
192
+ delayer.new(:low) { a += 4 }
193
+ assert_equal(0, a)
194
+ d.cancel
195
+ delayer.run
196
+ assert_equal(6, a)
197
+ end
198
+
199
+ def test_priority_cancel_center
200
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
201
+ default: :middle)
202
+ a = 0
203
+ delayer.new { a += 1 }
204
+ d = delayer.new { a += 2 }
205
+ delayer.new { a += 4 }
206
+ assert_equal(0, a)
207
+ d.cancel
208
+ delayer.run
209
+ assert_equal(5, a)
210
+
211
+ a = 0
212
+ delayer.new(:low) { a += 1 }
213
+ d = delayer.new(:high) { a += 2 }
214
+ delayer.new(:low) { a += 4 }
215
+ assert_equal(0, a)
216
+ d.cancel
217
+ delayer.run
218
+ assert_equal(5, a)
219
+
220
+ a = 0
221
+ delayer.new(:high) { a += 1 }
222
+ d = delayer.new(:low) { a += 2 }
223
+ delayer.new(:high) { a += 4 }
224
+ assert_equal(0, a)
225
+ d.cancel
226
+ delayer.run
227
+ assert_equal(5, a)
228
+ end
229
+
230
+ def test_priority_cancel_end
231
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
232
+ default: :middle)
233
+ a = 0
234
+ delayer.new { a += 1 }
235
+ delayer.new { a += 2 }
236
+ d = delayer.new { a += 4 }
237
+ assert_equal(0, a)
238
+ d.cancel
239
+ delayer.run
240
+ assert_equal(3, a)
241
+
242
+ a = 0
243
+ delayer.new(:low) { a += 1 }
244
+ delayer.new(:low) { a += 2 }
245
+ d = delayer.new(:high) { a += 4 }
246
+ assert_equal(0, a)
247
+ d.cancel
248
+ delayer.run
249
+ assert_equal(3, a)
250
+
251
+ a = 0
252
+ delayer.new(:high) { a += 1 }
253
+ delayer.new(:high) { a += 2 }
254
+ d = delayer.new(:low) { a += 4 }
255
+ assert_equal(0, a)
256
+ d.cancel
257
+ delayer.run
258
+ assert_equal(3, a)
259
+ end
260
+
261
+ def test_multithread_register
262
+ delayer = Delayer.generate_class
263
+ buffer = []
264
+ threads = []
265
+ 10.times do
266
+ threads << Thread.new do
267
+ 1000.times do |number|
268
+ delayer.new { buffer << number }
269
+ end
270
+ end
271
+ end
272
+ delayer.run
273
+ threads.each &:join
274
+ delayer.run
275
+ assert_equal(10000, buffer.size)
276
+ assert_equal((0..999).inject(&:+)*10, buffer.inject(&:+))
277
+ end
278
+
279
+ def test_nested
280
+ delayer = Delayer.generate_class
281
+ buffer = []
282
+ delayer.new { buffer << 1 }
283
+ delayer.new do
284
+ delayer.new { buffer << 3 }
285
+ delayer.new do
286
+ delayer.new { buffer << 5 }
287
+ delayer.new { buffer << 6 }
288
+ end
289
+ delayer.new { buffer << 4 }
290
+ end
291
+ delayer.new { buffer << 2 }
292
+
293
+ delayer.run
294
+ assert_equal([1,2,3,4,5,6], buffer)
295
+ end
296
+
297
+ def test_remain_hook
298
+ delayer = Delayer.generate_class expire: 0.01
299
+ a = []
300
+ delayer.register_remain_hook {
301
+ a << :remain
302
+ }
303
+ delayer.new { a << 0 }
304
+ delayer.new { a << 1; sleep 0.1 }
305
+ delayer.new { a << 2 }
306
+
307
+ delayer.run
308
+
309
+ delayer.new { a << 3 }
310
+ delayer.new { a << 4 }
311
+
312
+ delayer.run
313
+
314
+ assert_equal([:remain, 0, 1, :remain, 2, 3, 4], a)
315
+
316
+ end
317
+ end
@@ -0,0 +1,257 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'test/unit'
6
+ require 'delayer'
7
+
8
+ class TestPriorityDelayer < Test::Unit::TestCase
9
+ def test_asc
10
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
11
+ default: :middle)
12
+ buffer = []
13
+ delayer.new(:high) { buffer << 1 }
14
+ delayer.new(:middle) { buffer << 2 }
15
+ delayer.new(:low) { buffer << 3 }
16
+ delayer.run
17
+ assert_equal([1,2,3], buffer)
18
+ end
19
+
20
+ def test_desc
21
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
22
+ default: :middle)
23
+ buffer = []
24
+ delayer.new(:low) { buffer << 3 }
25
+ delayer.new(:middle) { buffer << 2 }
26
+ delayer.new(:high) { buffer << 1 }
27
+ delayer.run
28
+ assert_equal([1,2,3], buffer)
29
+ end
30
+
31
+ def test_complex
32
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
33
+ default: :middle)
34
+ buffer = []
35
+ delayer.new(:high) { buffer << 1 }
36
+ delayer.new(:middle) { buffer << 2 }
37
+ delayer.new(:low) { buffer << 3 }
38
+ delayer.new(:middle) { buffer << 4 }
39
+ delayer.new(:high) { buffer << 5 }
40
+ delayer.new(:middle) { buffer << 6 }
41
+ delayer.new(:low) { buffer << 7 }
42
+ delayer.new(:middle) { buffer << 8 }
43
+ delayer.new(:high) { buffer << 9 }
44
+ delayer.run
45
+ assert_equal([1,5,9,2,4,6,8,3,7], buffer)
46
+
47
+ buffer = []
48
+ delayer.new(:high) { buffer << 1 }
49
+ delayer.new(:low) { buffer << 2 }
50
+ delayer.new(:high) { buffer << 3 }
51
+ delayer.new(:low) { buffer << 4 }
52
+ delayer.run
53
+ assert_equal([1,3,2,4], buffer)
54
+ end
55
+
56
+ def test_timelimited
57
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
58
+ default: :middle,
59
+ expire: 0.01)
60
+ a = 0
61
+ delayer.new { sleep 0.1 }
62
+ delayer.new { a = 1 }
63
+
64
+ assert_equal(0, a)
65
+ delayer.run
66
+ assert_equal(0, a)
67
+ delayer.run
68
+ assert_equal(1, a)
69
+ end
70
+
71
+ def test_busy
72
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
73
+ default: :middle)
74
+ a = false
75
+ delayer.new { a = delayer.busy? }
76
+
77
+ assert_equal(false, a)
78
+ assert_equal(false, delayer.busy?)
79
+ delayer.run
80
+ assert_equal(false, delayer.busy?)
81
+ assert_equal(true, a)
82
+ end
83
+
84
+ def test_empty
85
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
86
+ default: :middle)
87
+ a = false
88
+ delayer.new { a = delayer.empty? }
89
+
90
+ assert_equal(false, a)
91
+ assert_equal(false, delayer.empty?)
92
+ delayer.run
93
+ assert_equal(true, delayer.empty?)
94
+ assert_equal(true, a)
95
+ end
96
+
97
+ def test_size
98
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
99
+ default: :middle)
100
+ a = 0
101
+ assert_equal(0, delayer.size)
102
+ delayer.new { a += 1 }
103
+ assert_equal(1, delayer.size)
104
+ delayer.new { a += 1 }
105
+ delayer.new { a += 1 }
106
+ assert_equal(3, delayer.size)
107
+ delayer.run
108
+ assert_equal(0, delayer.size)
109
+ end
110
+
111
+ def test_cancel_begin
112
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
113
+ default: :middle)
114
+ a = 0
115
+ d = delayer.new { a += 1 }
116
+ delayer.new { a += 2 }
117
+ delayer.new { a += 4 }
118
+ assert_equal(0, a)
119
+ d.cancel
120
+ delayer.run
121
+ assert_equal(6, a)
122
+
123
+ a = 0
124
+ d = delayer.new(:low) { a += 1 }
125
+ delayer.new(:high) { a += 2 }
126
+ delayer.new(:high) { a += 4 }
127
+ assert_equal(0, a)
128
+ d.cancel
129
+ delayer.run
130
+ assert_equal(6, a)
131
+
132
+ a = 0
133
+ d = delayer.new(:high) { a += 1 }
134
+ delayer.new(:low) { a += 2 }
135
+ delayer.new(:low) { a += 4 }
136
+ assert_equal(0, a)
137
+ d.cancel
138
+ delayer.run
139
+ assert_equal(6, a)
140
+ end
141
+
142
+ def test_cancel_center
143
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
144
+ default: :middle)
145
+ a = 0
146
+ delayer.new { a += 1 }
147
+ d = delayer.new { a += 2 }
148
+ delayer.new { a += 4 }
149
+ assert_equal(0, a)
150
+ d.cancel
151
+ delayer.run
152
+ assert_equal(5, a)
153
+
154
+ a = 0
155
+ delayer.new(:low) { a += 1 }
156
+ d = delayer.new(:high) { a += 2 }
157
+ delayer.new(:low) { a += 4 }
158
+ assert_equal(0, a)
159
+ d.cancel
160
+ delayer.run
161
+ assert_equal(5, a)
162
+
163
+ a = 0
164
+ delayer.new(:high) { a += 1 }
165
+ d = delayer.new(:low) { a += 2 }
166
+ delayer.new(:high) { a += 4 }
167
+ assert_equal(0, a)
168
+ d.cancel
169
+ delayer.run
170
+ assert_equal(5, a)
171
+ end
172
+
173
+ def test_cancel_end
174
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
175
+ default: :middle)
176
+ a = 0
177
+ delayer.new { a += 1 }
178
+ delayer.new { a += 2 }
179
+ d = delayer.new { a += 4 }
180
+ assert_equal(0, a)
181
+ d.cancel
182
+ delayer.run
183
+ assert_equal(3, a)
184
+
185
+ a = 0
186
+ delayer.new(:low) { a += 1 }
187
+ delayer.new(:low) { a += 2 }
188
+ d = delayer.new(:high) { a += 4 }
189
+ assert_equal(0, a)
190
+ d.cancel
191
+ delayer.run
192
+ assert_equal(3, a)
193
+
194
+ a = 0
195
+ delayer.new(:high) { a += 1 }
196
+ delayer.new(:high) { a += 2 }
197
+ d = delayer.new(:low) { a += 4 }
198
+ assert_equal(0, a)
199
+ d.cancel
200
+ delayer.run
201
+ assert_equal(3, a)
202
+ end
203
+
204
+ def test_multithread_register
205
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
206
+ default: :middle)
207
+ buffer = []
208
+ threads = []
209
+ 10.times do
210
+ threads << Thread.new do
211
+ 1000.times do |number|
212
+ delayer.new { buffer << number }
213
+ end
214
+ end
215
+ end
216
+ delayer.run
217
+ threads.each &:join
218
+ delayer.run
219
+ assert_equal(10000, buffer.size)
220
+ assert_equal((0..999).inject(&:+)*10, buffer.inject(&:+))
221
+ end
222
+
223
+ def test_nested
224
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low],
225
+ default: :middle)
226
+ buffer = []
227
+ delayer.new { buffer << 1 }
228
+ delayer.new do
229
+ delayer.new { buffer << 3 }
230
+ delayer.new do
231
+ delayer.new { buffer << 5 }
232
+ delayer.new { buffer << 6 }
233
+ end
234
+ delayer.new { buffer << 4 }
235
+ end
236
+ delayer.new { buffer << 2 }
237
+
238
+ delayer.run
239
+ assert_equal([1,2,3,4,5,6], buffer)
240
+ end
241
+
242
+ def test_invalid_priority
243
+ delayer = Delayer.generate_class(priority: [:high, :middle, :low])
244
+ buffer = []
245
+ assert_raise Delayer::InvalidPriorityError do
246
+ delayer.new(0) { buffer << 1 }
247
+ end
248
+ assert_raise Delayer::InvalidPriorityError do
249
+ delayer.new("middle") { buffer << 2 }
250
+ end
251
+ assert_raise Delayer::InvalidPriorityError do
252
+ delayer.new { buffer << 3 }
253
+ end
254
+ delayer.run
255
+ assert_equal([], buffer)
256
+ end
257
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: delayer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Toshiaki Asai
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: &15390660 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.2.3
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *15390660
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &18232940 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *18232940
36
+ description: Delay the processing
37
+ email:
38
+ - toshi.alternative@gmail.com
39
+ executables: []
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - .gitignore
44
+ - Gemfile
45
+ - LICENSE.txt
46
+ - README.md
47
+ - Rakefile
48
+ - delayer.gemspec
49
+ - lib/delayer.rb
50
+ - lib/delayer/error.rb
51
+ - lib/delayer/extend.rb
52
+ - lib/delayer/priority.rb
53
+ - lib/delayer/procedure.rb
54
+ - lib/delayer/version.rb
55
+ - test/test_delayer.rb
56
+ - test/test_priority.rb
57
+ homepage: ''
58
+ licenses:
59
+ - MIT
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 1.8.11
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Delay the processing
82
+ test_files:
83
+ - test/test_delayer.rb
84
+ - test/test_priority.rb