thread-task 2.0.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 716712aca5f16f5f7cce6e2dd080b2bc8977ab6b52cc1a450ff26daa03490e75
4
+ data.tar.gz: 5426b3d682dcba73903471e2920cc37758dd76a6526a2f32c579a6907075d1a0
5
+ SHA512:
6
+ metadata.gz: e120a53671fea648459b54cb97616291515c7bdd27ceb9849e2010ba5e5f4da6f48d81cf922f45d25d9db0b7d619c83cd33ad92366216da2437d697fe2926ba2
7
+ data.tar.gz: 666026187d04520ef1a388db270a912e4a6b49f341549a719c1e4aa94a10960c68908c317879f0c158018355fa333558a92ed09e939348c69f3077f65c25ecaa
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /.rspec_status
10
+ /vendor/
11
+ /var/
12
+ /log/
13
+ /Gemfile.*
14
+ *.bundle
15
+ *.so
16
+ *.o
17
+ *.a
18
+ *.pid
19
+ *.swp
20
+ *.log
21
+ *.log.*
22
+
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,73 @@
1
+
2
+ AllCops:
3
+ Exclude:
4
+ - '.*'
5
+ - '*'
6
+ - '*.gemspec'
7
+ - 'Gemfile*'
8
+ - 'bin/**'
9
+ - 'exe/**'
10
+ - 'config/**/*'
11
+ - 'spec/**/*'
12
+ - 'tmp/**/*'
13
+ - 'vendor/**/*'
14
+ TargetRubyVersion: 2.7
15
+
16
+ Layout/ExtraSpacing:
17
+ Enabled: false
18
+
19
+ Layout/SpaceAroundOperators:
20
+ Enabled: false
21
+
22
+ Layout/SpaceBeforeFirstArg:
23
+ Enabled: false
24
+
25
+ Layout/SpaceInsideParens:
26
+ Enabled: false
27
+
28
+ Layout/SpaceInsideArrayLiteralBrackets:
29
+ Enabled: false
30
+
31
+ Layout/SpaceInsideRangeLiteral:
32
+ Enabled: false
33
+
34
+ Layout/SpaceInsideReferenceBrackets:
35
+ Enabled: false
36
+
37
+ Layout/SpaceInsideStringInterpolation:
38
+ Enabled: false
39
+
40
+ Lint/AmbiguousBlockAssociation:
41
+ Enabled: false
42
+
43
+ Lint/EmptyWhen:
44
+ Enabled: false
45
+
46
+ Lint/ReturnInVoidContext:
47
+ Enabled: false
48
+
49
+ Lint/UselessAssignment:
50
+ Enabled: false
51
+
52
+ Metrics/BlockLength:
53
+ Enabled: false
54
+
55
+ Metrics/LineLength:
56
+ Enabled: false
57
+ Max: 120
58
+
59
+ Metrics/MethodLength:
60
+ Enabled: false
61
+
62
+ Style/Documentation:
63
+ Enabled: true
64
+
65
+ Style/FrozenStringLiteralComment:
66
+ Enabled: false
67
+
68
+ Style/NumericPredicate:
69
+ Enabled: false
70
+
71
+ Style/StringLiterals:
72
+ Enabled: false
73
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in thread-task.gemspec
4
+ gemspec
data/README.adoc ADDED
@@ -0,0 +1,224 @@
1
+ = Thread::Task
2
+
3
+ A wrapper library of Thread class for easily describing parallel processing.
4
+
5
+ == Features
6
+
7
+ * Thread::Task is a configuration that allows you to briefly describe the configuration often used in parallel processing.
8
+ * Thread::Task::Pool limits the number of parallel executions of Thread::Task.
9
+ * Runs only once within the specified timelimit.
10
+
11
+ == Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ [source,ruby]
16
+ ----
17
+ gem 'thread-task'
18
+ ----
19
+
20
+ And then execute:
21
+
22
+ $ bundle install
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install thread-task
27
+ or
28
+ $ gem install -l thread-task-x.x.x.gem
29
+
30
+ == Usage
31
+
32
+ ::Thread::Task has alias ::Task.
33
+
34
+ === Start parallel execution, wait for completion and get result.
35
+
36
+ [source,ruby]
37
+ ----
38
+ require "thread/task"
39
+
40
+ task = Task.new do
41
+ sleep 2
42
+ Time.now
43
+ end
44
+ p task.value
45
+ ----
46
+
47
+ === Limit the max count of parallel executions.
48
+
49
+ [source,ruby]
50
+ ----
51
+ require "thread/task"
52
+
53
+ tasks = (0...10).map do |i|
54
+ p [i]
55
+ Task.new( i, count: 3 ) do |j|
56
+ p [" ->", j]
57
+ sleep( rand * 2 )
58
+ p ["<- ", j]
59
+ end
60
+ end
61
+
62
+ tasks.each(&:join)
63
+ ----
64
+
65
+ === Limit the max count of parallel executions with a Task::Pool.
66
+
67
+ [source,ruby]
68
+ ----
69
+ require "thread/task"
70
+
71
+ pool = Task::Pool.new(3)
72
+
73
+ tasks1 = (0...4).map do |i|
74
+ p [i]
75
+ Task.new( i, pool: pool ) do |j|
76
+ p [" ->", j]
77
+ sleep( rand * 2 )
78
+ p ["<- ", j]
79
+ end
80
+ end
81
+ tasks2 = (4...8).map do |i|
82
+ p [i]
83
+ Task.new( i, pool: pool ) do |j|
84
+ p [" ->", j]
85
+ sleep( rand * 2 )
86
+ p ["<- ", j]
87
+ end
88
+ end
89
+
90
+ tasks1.each(&:join)
91
+ tasks2.each(&:join)
92
+ ----
93
+
94
+ === Invoke the block only once at the beginning, and ignoring recalls within the time limit.
95
+
96
+ [source,ruby]
97
+ ----
98
+ require "thread/task"
99
+
100
+ tasks = (1..10).map do |i|
101
+ sleep 0.1
102
+ Task.once( i, guard:3 ) do |j|
103
+ p j
104
+ end
105
+ end
106
+
107
+ tasks.each(&:join)
108
+ ----
109
+
110
+ === When there is no recall within the time limit, invoke the block only once at the end.
111
+
112
+ [source,ruby]
113
+ ----
114
+ require "thread/task"
115
+
116
+ tasks = (1..10).map do |i|
117
+ sleep 0.1
118
+ Task.once( i, delay:3 ) do |j|
119
+ p j
120
+ end
121
+ end
122
+
123
+ tasks.each(&:join)
124
+ ----
125
+
126
+ == Reference
127
+
128
+ === Create a new Thread::Task.
129
+
130
+ [source,ruby]
131
+ ----
132
+ Thread::Task.new( *args, pool: nil, count: nil, &block )
133
+ ----
134
+
135
+ * Result:
136
+ ** Thread::Task object.
137
+
138
+ * Parameter:
139
+ ** args: Pass args as is to the block.
140
+ ** pool: Thread::Task::Pool object. (default: nil)
141
+ ** count: Max count of parallel executions. (default: nil)
142
+ ** block: callback action.
143
+
144
+ * Block Parameter:
145
+ ** args: Treat args as local variables specific to that thread.
146
+
147
+ === Wait for thread stop. Ignore thread exceptions.
148
+
149
+ [source,ruby]
150
+ ----
151
+ Thread::Task#join
152
+ ----
153
+
154
+ * Result:
155
+ ** nil
156
+
157
+ * Parameter:
158
+ ** none.
159
+
160
+ === Wait for the thread to stop and get the result. Detect the thread exception.
161
+
162
+ [source,ruby]
163
+ ----
164
+ Thread::Task#value
165
+ ----
166
+
167
+ * Result:
168
+ ** The execution result of the block.
169
+
170
+ * Parameter:
171
+ ** none.
172
+
173
+ === Cancel the execution of the thread.
174
+
175
+ [source,ruby]
176
+ ----
177
+ Thread::Task#cancel
178
+ ----
179
+
180
+ * Result:
181
+ ** nil.
182
+
183
+ * Parameter:
184
+ ** none.
185
+
186
+ === Create a new Thread::Pool.
187
+
188
+ [source,ruby]
189
+ ----
190
+ Thread::Task.once( *args, delay: nil, guard: nil, &block )
191
+ ----
192
+
193
+ * Result:
194
+ ** Thread::Task object.
195
+
196
+ * Parameter:
197
+ ** args: Pass args as is to the block.
198
+ ** delay: Wait for delay second before call block. (default: nil)
199
+ ** guard: Wait for guard second after call block. (default: nil)
200
+ ** ident: Task identifier. (default: nil )
201
+ ** block: callback action.
202
+
203
+ === Create a new Thread::Pool.
204
+
205
+ [source,ruby]
206
+ ----
207
+ Thread::Pool.new( count )
208
+ ----
209
+
210
+ * Result:
211
+ ** Thread::Pool object.
212
+
213
+ * Parameter:
214
+ ** count: Max count of parallel executions.
215
+
216
+ == Contributing
217
+
218
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yorihara/thread-task.
219
+
220
+ == License
221
+
222
+ The gem is available as open source under the terms of the http://opensource.org/licenses/MIT[MIT License].
223
+
224
+ Copyright (c) yorihara <orihara.yasumi@gmail.com>
data/README.ja.adoc ADDED
@@ -0,0 +1,224 @@
1
+ = Thread::Task
2
+
3
+ 並列処理を簡単に記述するための Thread クラスのラッパーライブラリ.
4
+
5
+ == 特徴
6
+
7
+ * Thread::Task は並列処理でよく使う構成を簡潔に記述できるようにしたもの.
8
+ * Thread::Task::Pool は Thread::Task の並列実行数を制限する.
9
+ * 指定された制限時間内に一度だけ実行する.
10
+
11
+ == 導入
12
+
13
+ アプリの Gemfile にこの行を追加
14
+
15
+ [source,ruby]
16
+ ----
17
+ gem 'thread-task'
18
+ ----
19
+
20
+ それから実行
21
+
22
+ $ bundle install
23
+
24
+ または次のように手動で導入
25
+
26
+ $ gem install thread-task
27
+ or
28
+ $ gem install -l thread-task-x.x.x.gem
29
+
30
+ == 使い方
31
+
32
+ ::Thread::Task は ::Task の別名をもつ.
33
+
34
+ === 並列実行を開始して完了を待って結果を得る.
35
+
36
+ [source,ruby]
37
+ ----
38
+ require "thread/task"
39
+
40
+ task = Task.new do
41
+ sleep 2
42
+ Time.now
43
+ end
44
+ p task.value
45
+ ----
46
+
47
+ === 並列実行の最大数を制限する.
48
+
49
+ [source,ruby]
50
+ ----
51
+ require "thread/task"
52
+
53
+ tasks = (0...10).map do |i|
54
+ p [i]
55
+ Task.new( i, count: 3 ) do |j|
56
+ p [" ->", j]
57
+ sleep( rand * 2 )
58
+ p ["<- ", j]
59
+ end
60
+ end
61
+
62
+ tasks.each(&:join)
63
+ ----
64
+
65
+ === ひとつのプールで並列実行の最大数を制限する.
66
+
67
+ [source,ruby]
68
+ ----
69
+ require "thread/task"
70
+
71
+ pool = Task::Pool.new(3)
72
+
73
+ tasks1 = (0...4).map do |i|
74
+ p [i]
75
+ Task.new( i, pool: pool ) do |j|
76
+ p [" ->", j]
77
+ sleep( rand * 2 )
78
+ p ["<- ", j]
79
+ end
80
+ end
81
+ tasks2 = (4...8).map do |i|
82
+ p [i]
83
+ Task.new( i, pool: pool ) do |j|
84
+ p [" ->", j]
85
+ sleep( rand * 2 )
86
+ p ["<- ", j]
87
+ end
88
+ end
89
+
90
+ tasks1.each(&:join)
91
+ tasks2.each(&:join)
92
+ ----
93
+
94
+ === 最初に一度だけブロックを呼び出して、制限時間内の再呼び出しは無視する.
95
+
96
+ [source,ruby]
97
+ ----
98
+ require "thread/task"
99
+
100
+ tasks = (1..10).map do |i|
101
+ sleep 0.1
102
+ Task.once( i, guard:3 ) do |j|
103
+ p j
104
+ end
105
+ end
106
+
107
+ tasks.each(&:join)
108
+ ----
109
+
110
+ === 制限時間内に再呼び出しがないとき、最後に一度だけブロックを呼び出す.
111
+
112
+ [source,ruby]
113
+ ----
114
+ require "thread/task"
115
+
116
+ tasks = (1..10).map do |i|
117
+ sleep 0.1
118
+ Task.once( i, delay:3 ) do |j|
119
+ p j
120
+ end
121
+ end
122
+
123
+ tasks.each(&:join)
124
+ ----
125
+
126
+ == リファレンス
127
+
128
+ === 新たな Thread::Task を作成する.
129
+
130
+ [source,ruby]
131
+ ----
132
+ Thread::Task.new( *args, pool: nil, count: nil, &block )
133
+ ----
134
+
135
+ * Result:
136
+ ** Thread::Task オブジェクト.
137
+
138
+ * Parameter:
139
+ ** args: args はそのままブロックに渡す.
140
+ ** pool: Thread::Task::Pool オブジェクト. (default: nil)
141
+ ** count: 並列実行の最大数. (default: nil)
142
+ ** block: コールバック動作.
143
+
144
+ * Block Parameter:
145
+ ** args: args をそのスレッド固有のローカル変数として扱う.
146
+
147
+ === スレッド停止を待つ. スレッドの例外を無視する.
148
+
149
+ [source,ruby]
150
+ ----
151
+ Thread::Task#join
152
+ ----
153
+
154
+ * Result:
155
+ ** nil
156
+
157
+ * Parameter:
158
+ ** なし.
159
+
160
+ === スレッド停止を待って結果を得る. スレッドの例外を検出する.
161
+
162
+ [source,ruby]
163
+ ----
164
+ Thread::Task#value
165
+ ----
166
+
167
+ * Result:
168
+ ** ブロックの実行結果.
169
+
170
+ * Parameter:
171
+ ** なし.
172
+
173
+ === スレッドの実行を取り消す.
174
+
175
+ [source,ruby]
176
+ ----
177
+ Thread::Task#cancel
178
+ ----
179
+
180
+ * Result:
181
+ ** nil.
182
+
183
+ * Parameter:
184
+ ** なし.
185
+
186
+ === 短時間のうちに同じ行が再び呼び出された際に、一度だけ実行する.
187
+
188
+ [source,ruby]
189
+ ----
190
+ Thread::Task.once( *args, delay: nil, guard: nil, ident: nil, &block )
191
+ ----
192
+
193
+ * Result:
194
+ ** Thread::Task オブジェクト.
195
+
196
+ * Parameter:
197
+ ** args: args はそのままブロックに渡す.
198
+ ** delay: 実行前に待機する秒数. (default: nil)
199
+ ** guard: 実行後に保護する秒数. (default: nil)
200
+ ** ident: タスク識別子. (default: nil )
201
+ ** block: コールバック動作.
202
+
203
+ === 新たな Thread::Pool を作成する.
204
+
205
+ [source,ruby]
206
+ ----
207
+ Thread::Pool.new( count )
208
+ ----
209
+
210
+ * Result:
211
+ ** Thread::Pool オブジェクト.
212
+
213
+ * Parameter:
214
+ ** count: 並列実行の最大数.
215
+
216
+ == 貢献
217
+
218
+ 不具合報告とプルリクエストは GitHub https://github.com/yorihara/thread-task まで.
219
+
220
+ == ライセンス
221
+
222
+ この Gem は、 http://opensource.org/licenses/MIT[MITライセンス] の条件に基づいてオープンソースとして入手できる.
223
+
224
+ Copyright (c) yorihara <orihara.yasumi@gmail.com>
data/Rakefile ADDED
@@ -0,0 +1,96 @@
1
+ require "bundler/gem_helper"
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ class Bundler::GemHelper
10
+
11
+ def git_archive( dir = "../zip" )
12
+ FileUtils.mkdir_p dir
13
+ dest_path = File.join(dir, "#{name}-#{version}.zip")
14
+ cmnd = "git archive --format zip --prefix=#{name}/ HEAD > #{dest_path}"
15
+
16
+ out, code = sh_with_status( cmnd )
17
+ raise "Couldn't archive gem," unless code == 0
18
+
19
+ Bundler.ui.confirm "#{name} #{version} archived to #{dest_path}."
20
+ end
21
+
22
+ def git_push
23
+ ver = version.to_s
24
+
25
+ cmnd = "git push origin #{ver} "
26
+ out, code = sh_with_status( cmnd )
27
+ raise "Couldn't git push origin." unless code == 0
28
+
29
+ cmnd = "git push "
30
+ out, code = sh_with_status( cmnd )
31
+ raise "Couldn't git push." unless code == 0
32
+
33
+ Bundler.ui.confirm "Git Push #{ver}."
34
+ end
35
+
36
+ def update_version( new_version )
37
+ version_filename = %x[ find . -type f -name "version.rb" | grep -v vendor | head -1 ].chomp
38
+ version_pathname = File.expand_path( version_filename )
39
+ lines = File.open( version_pathname ).read
40
+ lines = lines.gsub( /VERSION\s*=\s*\"\d+\.\d+\.\d+\"/, "VERSION = \"#{new_version}\"" )
41
+ File.open( version_pathname, "w" ) do |file|
42
+ file.write( lines )
43
+ end
44
+
45
+ cmnd = "git add #{version_pathname} "
46
+ out, code = sh_with_status( cmnd )
47
+ raise "Couldn't git add," unless code == 0
48
+
49
+ cmnd = "git commit -m '#{new_version}' "
50
+ out, code = sh_with_status( cmnd )
51
+ raise "Couldn't git commit." unless code == 0
52
+
53
+ cmnd = "git tag #{new_version} "
54
+ out, code = sh_with_status( cmnd )
55
+ raise "Couldn't git tag." unless code == 0
56
+
57
+ Bundler.ui.confirm "Update Tags to #{new_version}."
58
+ end
59
+
60
+ end
61
+
62
+ Bundler::GemHelper.new(Dir.pwd).instance_eval do
63
+
64
+ desc "Archive #{name}-#{version}.zip from repository"
65
+ task 'zip' do
66
+ git_archive
67
+ end
68
+
69
+ desc "Git Push"
70
+ task 'push' do
71
+ git_push
72
+ end
73
+
74
+ desc "Update Version Tiny"
75
+ task 'tiny' do
76
+ major, minor, tiny = version.to_s.split('.')
77
+ new_version = [major, minor, tiny.to_i + 1].join('.')
78
+ update_version( new_version )
79
+ end
80
+
81
+ desc "Update Version Minor"
82
+ task 'minor' do
83
+ major, minor, tiny = version.to_s.split('.')
84
+ new_version = [major, minor.to_i + 1, 0].join('.')
85
+ update_version( new_version )
86
+ end
87
+
88
+ desc "Update Version Major"
89
+ task 'major' do
90
+ major, minor, tiny = version.to_s.split('.')
91
+ new_version = [major.to_i + 1, 0, 0].join('.')
92
+ update_version( new_version )
93
+ end
94
+
95
+ end
96
+
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "thread/task"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ require "thread/task/version"
2
+ require "thread/task/base"
3
+
4
+ ::Task = ::Thread::Task unless defined?(::Task)
5
+
@@ -0,0 +1,139 @@
1
+ require "monitor"
2
+
3
+ class ::Thread
4
+ class Task
5
+
6
+ class Pool
7
+ attr_reader :rest
8
+
9
+ def initialize( size )
10
+ @rest = size
11
+ @monitor = Monitor.new
12
+ @lock_cond = @monitor.new_cond
13
+ end
14
+
15
+ def acquire
16
+ @monitor.synchronize do
17
+ @lock_cond.wait_while{ @rest == 0 }
18
+ @rest -= 1
19
+ end
20
+ end
21
+
22
+ def release
23
+ @monitor.synchronize do
24
+ @rest += 1
25
+ @lock_cond.signal
26
+ end
27
+ end
28
+ end
29
+
30
+ @@pool = ::Hash.new
31
+
32
+ def initialize( *args, pool: nil, count: nil, report_on_exception: false, &block )
33
+ raise ::ArgumentError, "block required." if block.nil?
34
+
35
+ if pool.nil? and count.nil?
36
+ @thread = ::Thread.start( args ) do |args_|
37
+ ::Thread.current.report_on_exception = report_on_exception
38
+ block.call( *args_ )
39
+ end
40
+
41
+ elsif pool and pool.is_a?(::Thread::Task::Pool)
42
+ @thread = ::Thread.start( args ) do |args_|
43
+ ::Thread.current.report_on_exception = report_on_exception
44
+ pool.acquire
45
+ begin
46
+ block.call( *args_ )
47
+ ensure
48
+ pool.release
49
+ end
50
+ end
51
+
52
+ elsif count and count.is_a? ::Integer and count > 0
53
+ key = caller[1]
54
+ unless ( pool = @@pool[key] )
55
+ pool = ::Thread::Task::Pool.new( count )
56
+ @@pool[key] = pool
57
+ end
58
+
59
+ @thread = ::Thread.start( args ) do |args_|
60
+ ::Thread.current.report_on_exception = report_on_exception
61
+ pool.acquire
62
+ begin
63
+ block.call( *args_ )
64
+ ensure
65
+ pool.release
66
+ end
67
+ end
68
+
69
+ else
70
+ raise ::ArgumentError, "Nil or size of Thread::Task::Pool object expected."
71
+
72
+ end
73
+ end
74
+
75
+ def join
76
+ @thread.join
77
+ end
78
+
79
+ def value
80
+ @thread.value
81
+ end
82
+
83
+ def cancel
84
+ @thread.kill
85
+ nil
86
+ end
87
+
88
+ class Counter
89
+ def initialize
90
+ @count = 0
91
+ @mutex = Mutex.new
92
+ end
93
+
94
+ def incr
95
+ @mutex.synchronize do
96
+ @count += 1
97
+ end
98
+ end
99
+
100
+ def decr
101
+ @mutex.synchronize do
102
+ @count -= 1 if @count > 0
103
+ @count
104
+ end
105
+ end
106
+
107
+ def reset
108
+ @mutex.synchronize do
109
+ @count = 0
110
+ end
111
+ end
112
+ end
113
+
114
+ @@counter = ::Hash.new{|h,k| h[k] = Counter.new }
115
+
116
+ def Task.once( *args, delay: nil, guard: nil, ident: nil, &block )
117
+ key = ( ident || caller[0] ).to_s
118
+ if delay and delay.is_a? ::Numeric and delay > 0
119
+ @@counter[key].incr
120
+ ::Thread::Task.new( key ) do |key_|
121
+ ::Kernel.sleep delay
122
+ count = @@counter[key_].decr
123
+ block.call( *args ) if count == 0
124
+ end
125
+ elsif guard and guard.is_a? ::Numeric and guard > 0
126
+ count = @@counter[key].incr
127
+ block.call( *args ) if count == 1
128
+ ::Thread::Task.new( key ) do |key_|
129
+ ::Kernel.sleep guard
130
+ @@counter[key_].decr
131
+ end
132
+ else
133
+ raise ::ArgumentError, "delay or guard time expected."
134
+ end
135
+ end
136
+
137
+ end
138
+ end
139
+
@@ -0,0 +1,5 @@
1
+ class ::Thread
2
+ class Task
3
+ VERSION = "2.0.0"
4
+ end
5
+ end
data/sample/base_1.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "thread/task"
2
+
3
+ task = Task.new do
4
+ sleep 2
5
+ Time.now
6
+ end
7
+ p task.value
8
+
@@ -0,0 +1,12 @@
1
+ require "thread/task"
2
+
3
+ tasks = (0...8).map do |i|
4
+ Task.new( i, count:3 ) do |j|
5
+ p [" ->", j]
6
+ sleep rand*2
7
+ p ["<- ", j]
8
+ end
9
+ end
10
+
11
+ tasks.each(&:join)
12
+
@@ -0,0 +1,22 @@
1
+ require "thread/task"
2
+
3
+ pool = Task::Pool.new( 3 )
4
+
5
+ tasks1 = (0...4).map do |i|
6
+ Task.new( i, pool: pool ) do |j|
7
+ p [" ->", j]
8
+ sleep(rand*2)
9
+ p ["<- ", j]
10
+ end
11
+ end
12
+ tasks2 = (4...8).map do |i|
13
+ Task.new( i, pool: pool ) do |j|
14
+ p [" ->", j]
15
+ sleep(rand*2)
16
+ p ["<- ", j]
17
+ end
18
+ end
19
+
20
+ tasks1.each(&:join)
21
+ tasks2.each(&:join)
22
+
@@ -0,0 +1,10 @@
1
+ require "thread/task"
2
+
3
+ tasks = (1...8).map do |i|
4
+ sleep 0.1
5
+ Task.once( i, delay:3 ) do |j|
6
+ p j
7
+ end
8
+ end
9
+
10
+ tasks.each(&:join)
@@ -0,0 +1,20 @@
1
+ require "thread/task"
2
+
3
+ ident = "foobar"
4
+
5
+ tasks1 = (1...4).map do |i|
6
+ sleep 0.1
7
+ Task.once( i, delay:3, ident: ident ) do |j|
8
+ p j
9
+ end
10
+ end
11
+ tasks2 = (4...8).map do |i|
12
+ sleep 0.1
13
+ Task.once( i, delay:3, ident: ident ) do |j|
14
+ p j
15
+ end
16
+ end
17
+
18
+ tasks1.each(&:join)
19
+ tasks2.each(&:join)
20
+
@@ -0,0 +1,10 @@
1
+ require "thread/task"
2
+
3
+ tasks = (1...8).map do |i|
4
+ sleep 0.1
5
+ Task.once( i, guard:3 ) do |j|
6
+ p j
7
+ end
8
+ end
9
+
10
+ tasks.each(&:join)
@@ -0,0 +1,20 @@
1
+ require "thread/task"
2
+
3
+ ident = "foobar"
4
+
5
+ tasks1 = (1...4).map do |i|
6
+ sleep 0.1
7
+ Task.once( i, guard:3, ident: ident ) do |j|
8
+ p j
9
+ end
10
+ end
11
+ tasks2 = (4...8).map do |i|
12
+ sleep 0.1
13
+ Task.once( i, guard:3, ident: ident ) do |j|
14
+ p j
15
+ end
16
+ end
17
+
18
+ tasks1.each(&:join)
19
+ tasks2.each(&:join)
20
+
@@ -0,0 +1,22 @@
1
+
2
+ require "thread/task"
3
+
4
+ begin
5
+ task = Task.new do
6
+ sleep 1
7
+ raise "die now"
8
+ end
9
+
10
+ p :wait
11
+ sleep 2
12
+
13
+ p :value
14
+ p task.value
15
+
16
+ p :do_not_reach
17
+
18
+ rescue => e
19
+ p [e.message, e.backtrace.shift]
20
+
21
+ end
22
+
@@ -0,0 +1,22 @@
1
+
2
+ require "thread/task"
3
+
4
+ begin
5
+ task = Task.new( count: 1 ) do
6
+ sleep 1
7
+ raise "die now"
8
+ end
9
+
10
+ p :wait
11
+ sleep 2
12
+
13
+ p :join
14
+ p task.join
15
+
16
+ p :done
17
+
18
+ rescue => e
19
+ p [e.message, e.backtrace.shift]
20
+
21
+ end
22
+
@@ -0,0 +1,23 @@
1
+ require_relative 'lib/thread/task/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "thread-task"
5
+ spec.version = Thread::Task::VERSION
6
+ spec.authors = ["yorihara"]
7
+ spec.email = ["orihara.yasumi@gmail.com"]
8
+
9
+ spec.summary = %q{ Wrapper library for Thread class for easily describing parallel processing. }
10
+ spec.description = %q{ Wrapper library of Thread class. Thread::Task, Thrad::Task::Pool }
11
+ spec.homepage = "https://github.com/yorihara/thread-task/"
12
+ spec.license = "MIT"
13
+
14
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
15
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ end
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec"
23
+ end
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thread-task
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - yorihara
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-05-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: " Wrapper library of Thread class. Thread::Task, Thrad::Task::Pool "
42
+ email:
43
+ - orihara.yasumi@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".rspec"
50
+ - ".rubocop.yml"
51
+ - Gemfile
52
+ - README.adoc
53
+ - README.ja.adoc
54
+ - Rakefile
55
+ - bin/console
56
+ - bin/setup
57
+ - lib/thread/task.rb
58
+ - lib/thread/task/base.rb
59
+ - lib/thread/task/version.rb
60
+ - sample/base_1.rb
61
+ - sample/base_pool_1.rb
62
+ - sample/base_pool_2.rb
63
+ - sample/once_delay_1.rb
64
+ - sample/once_delay_2.rb
65
+ - sample/once_guard_1.rb
66
+ - sample/once_guard_2.rb
67
+ - sample/rescue_1.rb
68
+ - sample/rescue_2.rb
69
+ - thread-task.gemspec
70
+ homepage: https://github.com/yorihara/thread-task/
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubygems_version: 3.2.15
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: Wrapper library for Thread class for easily describing parallel processing.
93
+ test_files: []