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 +7 -0
- data/.gitignore +22 -0
- data/.rspec +3 -0
- data/.rubocop.yml +73 -0
- data/Gemfile +4 -0
- data/README.adoc +224 -0
- data/README.ja.adoc +224 -0
- data/Rakefile +96 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/thread/task.rb +5 -0
- data/lib/thread/task/base.rb +139 -0
- data/lib/thread/task/version.rb +5 -0
- data/sample/base_1.rb +8 -0
- data/sample/base_pool_1.rb +12 -0
- data/sample/base_pool_2.rb +22 -0
- data/sample/once_delay_1.rb +10 -0
- data/sample/once_delay_2.rb +20 -0
- data/sample/once_guard_1.rb +10 -0
- data/sample/once_guard_2.rb +20 -0
- data/sample/rescue_1.rb +22 -0
- data/sample/rescue_2.rb +22 -0
- data/thread-task.gemspec +23 -0
- metadata +93 -0
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
data/.rspec
ADDED
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
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
data/lib/thread/task.rb
ADDED
@@ -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
|
+
|
data/sample/base_1.rb
ADDED
@@ -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,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,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
|
+
|
data/sample/rescue_1.rb
ADDED
data/sample/rescue_2.rb
ADDED
data/thread-task.gemspec
ADDED
@@ -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: []
|