thread 0.1.4 → 0.1.5
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 +4 -4
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -9
- data/Gemfile +3 -0
- data/LICENSE.txt +13 -0
- data/README.md +42 -42
- data/Rakefile +4 -13
- data/lib/thread/channel.rb +1 -1
- data/lib/thread/every.rb +2 -2
- data/lib/thread/future.rb +1 -1
- data/lib/thread/pipe.rb +1 -1
- data/lib/thread/pool.rb +36 -28
- data/lib/thread/process.rb +1 -1
- data/lib/thread/promise.rb +1 -1
- data/{tests → spec/thread}/channel_spec.rb +0 -2
- data/{tests → spec/thread}/delay_spec.rb +0 -2
- data/{tests → spec/thread}/every_spec.rb +1 -3
- data/{tests → spec/thread}/future_spec.rb +4 -7
- data/{tests → spec/thread}/pipe_spec.rb +1 -3
- data/{tests → spec/thread}/promise_spec.rb +3 -5
- data/thread.gemspec +20 -17
- metadata +22 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19359ceb19e36b411191f6a1ad561f7d1d4494b1
|
4
|
+
data.tar.gz: 26aa332d8178f937334fb00c01b6d52767aa0164
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53b93154104816e06c93c0b4477aa1a65ebc9c878b9e8723881ccf3ea5e2f9ab41c8454b6889018fb0132e9ece4c6efcac3731bff77a987629f4e784ce9d9bfc
|
7
|
+
data.tar.gz: 8cd976ebd6c34ac6b0d62facda8da94d67e9fda638f4a62a1d0693c12742ac1a2afca100d4c330de3638a4ea79155c3b08afb01ab1e2ef659365da16f74e9ff9
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
CHANGED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
2
|
+
Version 2, December 2004
|
3
|
+
|
4
|
+
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
5
|
+
|
6
|
+
Everyone is permitted to copy and distribute verbatim or modified
|
7
|
+
copies of this license document, and changing it is allowed as long
|
8
|
+
as the name is changed.
|
9
|
+
|
10
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
11
|
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
12
|
+
|
13
|
+
0. You just DO WHAT THE FUCK YOU WANT TO.
|
data/README.md
CHANGED
@@ -1,8 +1,23 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# thread
|
2
|
+
|
3
|
+
[](https://travis-ci.org/meh/ruby-thread)
|
4
|
+
|
5
|
+
Various extensions to the thread library in ruby.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'thread'
|
12
|
+
|
13
|
+
Or install it yourself as:
|
14
|
+
|
15
|
+
$ gem install thread
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
### Pool
|
3
20
|
|
4
|
-
Pool
|
5
|
-
====
|
6
21
|
All the implementations I looked at were either buggy or wasted CPU resources
|
7
22
|
for no apparent reason, for example used a sleep of 0.01 seconds to then check for
|
8
23
|
readiness and stuff like this.
|
@@ -10,9 +25,6 @@ readiness and stuff like this.
|
|
10
25
|
This implementation uses standard locking functions to work properly across multiple Ruby
|
11
26
|
implementations.
|
12
27
|
|
13
|
-
Example
|
14
|
-
-------
|
15
|
-
|
16
28
|
```ruby
|
17
29
|
require 'thread/pool'
|
18
30
|
|
@@ -31,12 +43,9 @@ pool.shutdown
|
|
31
43
|
|
32
44
|
You should get 4 lols every 2 seconds and it should exit after 10 of them.
|
33
45
|
|
34
|
-
Channel
|
35
|
-
=======
|
36
|
-
This implements a channel where you can write messages and receive messages.
|
46
|
+
### Channel
|
37
47
|
|
38
|
-
|
39
|
-
-------
|
48
|
+
This implements a channel where you can write messages and receive messages.
|
40
49
|
|
41
50
|
```ruby
|
42
51
|
require 'thread/channel'
|
@@ -67,15 +76,12 @@ loop {
|
|
67
76
|
}
|
68
77
|
```
|
69
78
|
|
70
|
-
Pipe
|
71
|
-
|
79
|
+
### Pipe
|
80
|
+
|
72
81
|
A pipe allows you to execute various tasks on a set of data in parallel,
|
73
82
|
each datum inserted in the pipe is passed along through queues to the various
|
74
83
|
functions composing the pipe, the final result is inserted in the final queue.
|
75
84
|
|
76
|
-
Example
|
77
|
-
-------
|
78
|
-
|
79
85
|
```ruby
|
80
86
|
require 'thread/pipe'
|
81
87
|
|
@@ -85,16 +91,13 @@ p << 2
|
|
85
91
|
puts ~p # => 16
|
86
92
|
```
|
87
93
|
|
88
|
-
Process
|
89
|
-
|
94
|
+
### Process
|
95
|
+
|
90
96
|
A process helps reducing programming errors coming from race conditions and the
|
91
97
|
like, the only way to interact with a process is through messages.
|
92
98
|
|
93
99
|
Multiple processes should talk with eachother through messages.
|
94
100
|
|
95
|
-
Example
|
96
|
-
-------
|
97
|
-
|
98
101
|
```ruby
|
99
102
|
require 'thread/process'
|
100
103
|
|
@@ -108,15 +111,12 @@ p << 42
|
|
108
111
|
p << 23
|
109
112
|
```
|
110
113
|
|
111
|
-
Promise
|
112
|
-
|
114
|
+
### Promise
|
115
|
+
|
113
116
|
This implements the promise pattern, allowing you to pass around an object
|
114
117
|
where you can send a value and extract a value, in a thread-safe way, accessing
|
115
118
|
the value will wait for the value to be delivered.
|
116
119
|
|
117
|
-
Example
|
118
|
-
-------
|
119
|
-
|
120
120
|
```ruby
|
121
121
|
require 'thread/promise'
|
122
122
|
|
@@ -130,8 +130,8 @@ Thread.new {
|
|
130
130
|
puts ~p # => 42
|
131
131
|
```
|
132
132
|
|
133
|
-
Future
|
134
|
-
|
133
|
+
### Future
|
134
|
+
|
135
135
|
A future is somewhat a promise, except you pass it a block to execute in
|
136
136
|
another thread.
|
137
137
|
|
@@ -144,9 +144,6 @@ the block executed in an existing thread-pool.
|
|
144
144
|
|
145
145
|
You can also use the `Thread::Pool` helper `#future`
|
146
146
|
|
147
|
-
Example
|
148
|
-
-------
|
149
|
-
|
150
147
|
```ruby
|
151
148
|
require 'thread/future'
|
152
149
|
|
@@ -186,14 +183,11 @@ puts ~f # => 42
|
|
186
183
|
```
|
187
184
|
|
188
185
|
|
189
|
-
Delay
|
190
|
-
|
186
|
+
### Delay
|
187
|
+
|
191
188
|
A delay is kind of a promise, except the block is called when the value is
|
192
189
|
being accessed and the result is cached.
|
193
190
|
|
194
|
-
Example
|
195
|
-
-------
|
196
|
-
|
197
191
|
```ruby
|
198
192
|
require 'thread/delay'
|
199
193
|
|
@@ -204,15 +198,12 @@ d = Thread.delay {
|
|
204
198
|
puts ~d # => 42
|
205
199
|
```
|
206
200
|
|
207
|
-
Every
|
208
|
-
|
201
|
+
### Every
|
202
|
+
|
209
203
|
An every executes the block every given seconds and yields the value to the
|
210
204
|
every object, you can then check if the current value is old or how much time
|
211
205
|
is left until the second call is done.
|
212
206
|
|
213
|
-
Example
|
214
|
-
-------
|
215
|
-
|
216
207
|
```ruby
|
217
208
|
require 'net/http'
|
218
209
|
require 'thread/every'
|
@@ -227,3 +218,12 @@ loop do
|
|
227
218
|
puts ~e
|
228
219
|
end
|
229
220
|
```
|
221
|
+
|
222
|
+
## Contributing
|
223
|
+
|
224
|
+
1. Fork it ( https://github.com/meh/ruby-thread/fork )
|
225
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
226
|
+
3. Verify new and old specs are green (`rake`)
|
227
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
228
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
229
|
+
6. Create a new Pull Request
|
data/Rakefile
CHANGED
@@ -1,15 +1,6 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
3
|
|
4
|
-
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
|
6
|
-
task :
|
7
|
-
FileUtils.cd 'tests' do
|
8
|
-
sh 'rspec channel_spec.rb --backtrace --color --format doc'
|
9
|
-
sh 'rspec promise_spec.rb --backtrace --color --format doc'
|
10
|
-
sh 'rspec future_spec.rb --backtrace --color --format doc'
|
11
|
-
sh 'rspec delay_spec.rb --backtrace --color --format doc'
|
12
|
-
sh 'rspec pipe_spec.rb --backtrace --color --format doc'
|
13
|
-
sh 'rspec every_spec.rb --backtrace --color --format doc'
|
14
|
-
end
|
15
|
-
end
|
6
|
+
task :default => :spec
|
data/lib/thread/channel.rb
CHANGED
data/lib/thread/every.rb
CHANGED
@@ -31,7 +31,7 @@ class Thread::Every
|
|
31
31
|
|
32
32
|
@mutex.synchronize {
|
33
33
|
@at = Time.now
|
34
|
-
|
34
|
+
@value = value
|
35
35
|
@old = false
|
36
36
|
@exception = nil
|
37
37
|
}
|
@@ -172,7 +172,7 @@ class Thread::Every
|
|
172
172
|
}
|
173
173
|
end
|
174
174
|
|
175
|
-
private
|
175
|
+
private
|
176
176
|
def cond?
|
177
177
|
instance_variable_defined? :@cond
|
178
178
|
end
|
data/lib/thread/future.rb
CHANGED
data/lib/thread/pipe.rb
CHANGED
data/lib/thread/pool.rb
CHANGED
@@ -61,6 +61,7 @@ class Thread::Pool
|
|
61
61
|
return
|
62
62
|
else
|
63
63
|
@exception = reason
|
64
|
+
raise @exception if Thread::Pool.abort_on_exception
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
@@ -119,7 +120,7 @@ class Thread::Pool
|
|
119
120
|
|
120
121
|
@done = ConditionVariable.new
|
121
122
|
@done_mutex = Mutex.new
|
122
|
-
|
123
|
+
|
123
124
|
@todo = []
|
124
125
|
@workers = []
|
125
126
|
@timeouts = {}
|
@@ -200,29 +201,29 @@ class Thread::Pool
|
|
200
201
|
@done.wait @done_mutex
|
201
202
|
}
|
202
203
|
end
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
204
|
+
|
205
|
+
# Check if there are idle workers.
|
206
|
+
def idle?
|
207
|
+
@todo.length < @waiting
|
208
|
+
end
|
209
|
+
|
210
|
+
# Process Block when there is a idle worker if not block its returns
|
211
|
+
def idle (*args, &block)
|
212
|
+
while !idle?
|
213
|
+
@done_mutex.synchronize {
|
214
|
+
break if idle?
|
215
|
+
@done.wait @done_mutex
|
216
|
+
}
|
217
|
+
end
|
218
|
+
|
219
|
+
unless block
|
220
|
+
return
|
221
|
+
end
|
222
|
+
|
223
|
+
process *args, &block
|
224
|
+
|
225
|
+
end
|
226
|
+
|
226
227
|
# Add a task to the pool which will execute the block with the given
|
227
228
|
# argument.
|
228
229
|
#
|
@@ -337,7 +338,14 @@ class Thread::Pool
|
|
337
338
|
self
|
338
339
|
end
|
339
340
|
|
340
|
-
|
341
|
+
class << self
|
342
|
+
# If true, tasks will allow raised exceptions to pass through.
|
343
|
+
#
|
344
|
+
# Similar to Thread.abort_on_exception
|
345
|
+
attr_accessor :abort_on_exception
|
346
|
+
end
|
347
|
+
|
348
|
+
private
|
341
349
|
def wake_up_timeout
|
342
350
|
if defined? @pipes
|
343
351
|
@pipes.last.write_nonblock 'x' rescue nil
|
@@ -398,7 +406,7 @@ private
|
|
398
406
|
|
399
407
|
thread
|
400
408
|
end
|
401
|
-
|
409
|
+
|
402
410
|
def spawn_timeout_thread
|
403
411
|
@pipes = IO.pipe
|
404
412
|
@timeout = Thread.new {
|
@@ -428,7 +436,7 @@ private
|
|
428
436
|
}
|
429
437
|
|
430
438
|
@timeouts.reject! { |task, _| task.terminated? || task.finished? }
|
431
|
-
|
439
|
+
|
432
440
|
break if @shutdown == :now
|
433
441
|
end
|
434
442
|
}
|
@@ -446,4 +454,4 @@ class Thread
|
|
446
454
|
def self.pool (*args, &block)
|
447
455
|
Thread::Pool.new(*args, &block)
|
448
456
|
end
|
449
|
-
end
|
457
|
+
end
|
data/lib/thread/process.rb
CHANGED
data/lib/thread/promise.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
1
|
require 'thread/future'
|
4
2
|
|
5
3
|
describe Thread::Future do
|
6
4
|
it 'delivers a value properly' do
|
7
5
|
f = Thread.future {
|
8
|
-
sleep 0.
|
9
|
-
|
6
|
+
sleep 0.02
|
10
7
|
42
|
11
8
|
}
|
12
9
|
|
@@ -15,19 +12,19 @@ describe Thread::Future do
|
|
15
12
|
|
16
13
|
it 'properly checks if anything has been delivered' do
|
17
14
|
f = Thread.future {
|
18
|
-
sleep 0.
|
15
|
+
sleep 0.02
|
19
16
|
|
20
17
|
42
|
21
18
|
}
|
22
19
|
|
23
20
|
f.delivered?.should == false
|
24
|
-
sleep 0.
|
21
|
+
sleep 0.03
|
25
22
|
f.delivered?.should == true
|
26
23
|
end
|
27
24
|
|
28
25
|
it 'does not block when a timeout is passed' do
|
29
26
|
f = Thread.future {
|
30
|
-
sleep 0.
|
27
|
+
sleep 0.02
|
31
28
|
|
32
29
|
42
|
33
30
|
}
|
@@ -1,5 +1,3 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
1
|
require 'thread/pipe'
|
4
2
|
|
5
3
|
describe Thread::Pipe do
|
@@ -14,7 +12,7 @@ describe Thread::Pipe do
|
|
14
12
|
end
|
15
13
|
|
16
14
|
it 'empty works properly' do
|
17
|
-
p = Thread |-> d { sleep 0.
|
15
|
+
p = Thread |-> d { sleep 0.02; d * 2 } |-> d { d * 4 }
|
18
16
|
|
19
17
|
p.empty?.should == true
|
20
18
|
p.enq 42
|
@@ -1,5 +1,3 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
1
|
require 'thread/promise'
|
4
2
|
|
5
3
|
describe Thread::Promise do
|
@@ -7,7 +5,7 @@ describe Thread::Promise do
|
|
7
5
|
p = Thread.promise
|
8
6
|
|
9
7
|
Thread.new {
|
10
|
-
sleep 0.
|
8
|
+
sleep 0.02
|
11
9
|
|
12
10
|
p << 42
|
13
11
|
}
|
@@ -19,13 +17,13 @@ describe Thread::Promise do
|
|
19
17
|
p = Thread.promise
|
20
18
|
|
21
19
|
Thread.new {
|
22
|
-
sleep 0.
|
20
|
+
sleep 0.02
|
23
21
|
|
24
22
|
p << 42
|
25
23
|
}
|
26
24
|
|
27
25
|
p.delivered?.should == false
|
28
|
-
sleep 0.
|
26
|
+
sleep 0.03
|
29
27
|
p.delivered?.should == true
|
30
28
|
end
|
31
29
|
|
data/thread.gemspec
CHANGED
@@ -1,19 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
s.author = 'meh.'
|
5
|
-
s.email = 'meh@schizofreni.co'
|
6
|
-
s.homepage = 'http://github.com/meh/ruby-thread'
|
7
|
-
s.platform = Gem::Platform::RUBY
|
8
|
-
s.summary = 'Various extensions to the base thread library.'
|
9
|
-
s.description = 'Includes a thread pool, message passing capabilities, a recursive mutex, promise, future and delay.'
|
10
|
-
s.license = 'WTFPL'
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
11
4
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "thread"
|
7
|
+
spec.version = "0.1.5"
|
8
|
+
spec.authors = ["meh."]
|
9
|
+
spec.email = ["meh@schizofreni.co"]
|
10
|
+
spec.summary = %q{Various extensions to the base thread library.}
|
11
|
+
spec.description = %q{Includes a thread pool, message passing capabilities, a recursive mutex, promise, future and delay.}
|
12
|
+
spec.homepage = "http://github.com/meh/ruby-thread"
|
13
|
+
spec.license = "WTFPL"
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
}
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "rspec"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thread
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- meh.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -40,12 +40,17 @@ dependencies:
|
|
40
40
|
version: '0'
|
41
41
|
description: Includes a thread pool, message passing capabilities, a recursive mutex,
|
42
42
|
promise, future and delay.
|
43
|
-
email:
|
43
|
+
email:
|
44
|
+
- meh@schizofreni.co
|
44
45
|
executables: []
|
45
46
|
extensions: []
|
46
47
|
extra_rdoc_files: []
|
47
48
|
files:
|
49
|
+
- ".gitignore"
|
50
|
+
- ".rspec"
|
48
51
|
- ".travis.yml"
|
52
|
+
- Gemfile
|
53
|
+
- LICENSE.txt
|
49
54
|
- README.md
|
50
55
|
- Rakefile
|
51
56
|
- lib/thread/channel.rb
|
@@ -57,12 +62,12 @@ files:
|
|
57
62
|
- lib/thread/process.rb
|
58
63
|
- lib/thread/promise.rb
|
59
64
|
- lib/thread/recursive_mutex.rb
|
60
|
-
-
|
61
|
-
-
|
62
|
-
-
|
63
|
-
-
|
64
|
-
-
|
65
|
-
-
|
65
|
+
- spec/thread/channel_spec.rb
|
66
|
+
- spec/thread/delay_spec.rb
|
67
|
+
- spec/thread/every_spec.rb
|
68
|
+
- spec/thread/future_spec.rb
|
69
|
+
- spec/thread/pipe_spec.rb
|
70
|
+
- spec/thread/promise_spec.rb
|
66
71
|
- thread.gemspec
|
67
72
|
homepage: http://github.com/meh/ruby-thread
|
68
73
|
licenses:
|
@@ -84,9 +89,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
89
|
version: '0'
|
85
90
|
requirements: []
|
86
91
|
rubyforge_project:
|
87
|
-
rubygems_version: 2.
|
92
|
+
rubygems_version: 2.4.5
|
88
93
|
signing_key:
|
89
94
|
specification_version: 4
|
90
95
|
summary: Various extensions to the base thread library.
|
91
|
-
test_files:
|
96
|
+
test_files:
|
97
|
+
- spec/thread/channel_spec.rb
|
98
|
+
- spec/thread/delay_spec.rb
|
99
|
+
- spec/thread/every_spec.rb
|
100
|
+
- spec/thread/future_spec.rb
|
101
|
+
- spec/thread/pipe_spec.rb
|
102
|
+
- spec/thread/promise_spec.rb
|
92
103
|
has_rdoc:
|