threadz 0.1.3 → 1.0.0.beta
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.
- data/CHANGELOG +5 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +18 -0
- data/Rakefile +3 -92
- data/lib/threadz.rb +12 -0
- data/lib/threadz/thread_pool.rb +14 -7
- data/lib/threadz/version.rb +4 -0
- data/spec/atomic_integer_spec.rb +4 -4
- data/spec/threadz_spec.rb +27 -2
- data/threadz.gemspec +15 -54
- metadata +42 -42
- data/VERSION +0 -1
data/CHANGELOG
CHANGED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/Rakefile
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
# Adapted from the rake Rakefile.
|
2
|
-
|
3
1
|
require 'rubygems'
|
4
2
|
require 'rake/testtask'
|
5
|
-
require '
|
6
|
-
require '
|
3
|
+
require 'rdoc/task'
|
4
|
+
require 'rubygems/package_task'
|
7
5
|
require 'rubygems/source_info_cache'
|
8
6
|
require 'spec/rake/spectask'
|
9
|
-
|
7
|
+
require "bundler/gem_tasks"
|
10
8
|
|
11
9
|
spec = Gem::Specification.load(File.join(File.dirname(__FILE__), 'threadz.gemspec'))
|
12
10
|
|
@@ -14,22 +12,6 @@ desc "Default Task"
|
|
14
12
|
task 'default' => ['spec', 'rdoc']
|
15
13
|
|
16
14
|
|
17
|
-
desc "If you're building from sources, run this task first to setup the necessary dependencies"
|
18
|
-
task 'setup' do
|
19
|
-
windows = Config::CONFIG['host_os'] =~ /windows|cygwin|bccwin|cygwin|djgpp|mingw|mswin|wince/i
|
20
|
-
rb_bin = File.expand_path(Config::CONFIG['ruby_install_name'], Config::CONFIG['bindir'])
|
21
|
-
spec.dependencies.select { |dep| Gem::SourceIndex.from_installed_gems.search(dep).empty? }.each do |missing|
|
22
|
-
dep = Gem::Dependency.new(missing.name, missing.version_requirements)
|
23
|
-
spec = Gem::SourceInfoCache.search(dep, true, true).last
|
24
|
-
fail "#{dep} not found in local or remote repository!" unless spec
|
25
|
-
puts "Installing #{spec.full_name} ..."
|
26
|
-
args = [rb_bin, '-S', 'gem', 'install', spec.name, '-v', spec.version.to_s]
|
27
|
-
args.unshift('sudo') unless windows || ENV['GEM_HOME']
|
28
|
-
sh args.map{ |a| a.inspect }.join(' ')
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
|
33
15
|
desc "Run all test cases"
|
34
16
|
task 'spec' do |task|
|
35
17
|
exec 'spec -c -f n spec/*.rb spec/basic/*.rb'
|
@@ -57,80 +39,9 @@ task 'spec-stress', [:times] do |task, args|
|
|
57
39
|
puts "Done!"
|
58
40
|
end
|
59
41
|
|
60
|
-
# Create the documentation.
|
61
42
|
Rake::RDocTask.new do |rdoc|
|
62
43
|
rdoc.main = 'README.rdoc'
|
63
44
|
rdoc.rdoc_files.include('README.rdoc', 'lib/**/*.rb')
|
64
45
|
rdoc.title = "Threadz Thread Pool"
|
65
46
|
rdoc.rdoc_dir = 'doc'
|
66
47
|
end
|
67
|
-
|
68
|
-
|
69
|
-
gem = Rake::GemPackageTask.new(spec) do |pkg|
|
70
|
-
pkg.need_tar = true
|
71
|
-
pkg.need_zip = true
|
72
|
-
end
|
73
|
-
|
74
|
-
desc "Install the package locally"
|
75
|
-
task 'install'=>['setup', 'package'] do |task|
|
76
|
-
rb_bin = File.expand_path(Config::CONFIG['ruby_install_name'], Config::CONFIG['bindir'])
|
77
|
-
args = [rb_bin, '-S', 'gem', 'install', "pkg/#{spec.name}-#{spec.version}.gem"]
|
78
|
-
windows = Config::CONFIG['host_os'] =~ /windows|cygwin|bccwin|cygwin|djgpp|mingw|mswin|wince/i
|
79
|
-
args.unshift('sudo') unless windows || ENV['GEM_HOME']
|
80
|
-
sh args.map{ |a| a.inspect }.join(' ')
|
81
|
-
end
|
82
|
-
|
83
|
-
desc "Uninstall previously installed packaged"
|
84
|
-
task 'uninstall' do |task|
|
85
|
-
rb_bin = File.expand_path(Config::CONFIG['ruby_install_name'], Config::CONFIG['bindir'])
|
86
|
-
args = [rb_bin, '-S', 'gem', 'install', spec.name, '-v', spec.version.to_s]
|
87
|
-
windows = Config::CONFIG['host_os'] =~ /windows|cygwin|bccwin|cygwin|djgpp|mingw|mswin|wince/i
|
88
|
-
args.unshift('sudo') unless windows || ENV['GEM_HOME']
|
89
|
-
sh args.map{ |a| a.inspect }.join(' ')
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
task 'release'=>['setup', 'test', 'package'] do
|
94
|
-
|
95
|
-
require 'rubyforge'
|
96
|
-
changes = File.read('CHANGELOG')[/\d+.\d+.\d+.*\n((:?^[^\n]+\n)*)/]
|
97
|
-
File.open '.changes', 'w' do |file|
|
98
|
-
file.write changes
|
99
|
-
end
|
100
|
-
|
101
|
-
puts "Uploading #{spec.name} #{spec.version}"
|
102
|
-
files = Dir['pkg/*.{gem,tgz,zip}']
|
103
|
-
rubyforge = RubyForge.new
|
104
|
-
rubyforge.configure
|
105
|
-
rubyforge.login
|
106
|
-
rubyforge.userconfig.merge! 'release_changes'=>'.changes', 'preformatted'=>true
|
107
|
-
rubyforge.add_release spec.rubyforge_project.downcase, spec.name.downcase, spec.version.to_s, *files
|
108
|
-
rm_f '.changes'
|
109
|
-
puts "Release #{spec.version} uploaded"
|
110
|
-
end
|
111
|
-
|
112
|
-
task 'clobber' do
|
113
|
-
rm_f '.changes'
|
114
|
-
end
|
115
|
-
|
116
|
-
desc "Run all examples with RCov"
|
117
|
-
Spec::Rake::SpecTask.new('spec:rcov') do |t|
|
118
|
-
t.spec_files = FileList['spec/**/*.rb']
|
119
|
-
t.rcov = true
|
120
|
-
t.rcov_opts = ['--exclude', 'spec']
|
121
|
-
end
|
122
|
-
|
123
|
-
begin
|
124
|
-
require 'jeweler'
|
125
|
-
Jeweler::Tasks.new do |gemspec|
|
126
|
-
gemspec.name = "threadz"
|
127
|
-
gemspec.summary = "An easy Ruby threadpool library."
|
128
|
-
gemspec.description = "A Ruby threadpool library to handle threadpools and make batch jobs easier."
|
129
|
-
gemspec.email = "nanodeath@gmail.com"
|
130
|
-
gemspec.homepage = "http://github.com/nanodeath/threadz"
|
131
|
-
gemspec.authors = ["Max Aller"]
|
132
|
-
end
|
133
|
-
Jeweler::GemcutterTasks.new
|
134
|
-
rescue LoadError
|
135
|
-
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
136
|
-
end
|
data/lib/threadz.rb
CHANGED
@@ -19,5 +19,17 @@
|
|
19
19
|
|
20
20
|
require 'thread'
|
21
21
|
|
22
|
+
require "threadz/version"
|
23
|
+
|
24
|
+
module Threadz
|
25
|
+
DEBUG = ENV['THREADZ_DEBUG'] == "1"
|
26
|
+
|
27
|
+
def Threadz.dputs(string)
|
28
|
+
puts(string) if DEBUG
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Threadz::dputs("Loading threadz")
|
33
|
+
|
22
34
|
['atomic_integer', 'sleeper', 'directive', 'batch', 'thread_pool'].each { |lib| require File.join(File.dirname(__FILE__), 'threadz', lib) }
|
23
35
|
|
data/lib/threadz/thread_pool.rb
CHANGED
@@ -5,11 +5,11 @@ module Threadz
|
|
5
5
|
# The ThreadPool class contains all the threads available to whatever context
|
6
6
|
# has access to it.
|
7
7
|
class ThreadPool
|
8
|
-
# Default setting for kill threshold
|
8
|
+
# Default setting for kill threshold: 10
|
9
9
|
KILL_THRESHOLD = 10
|
10
|
-
# Setting for how much to decrement current kill score by for each queued job
|
10
|
+
# Setting for how much to decrement current kill score by for each queued job: 1
|
11
11
|
THREADS_BUSY_SCORE = 1
|
12
|
-
# Setting for how much to increment current kill score by for *each* idle thread
|
12
|
+
# Setting for how much to increment current kill score by for *each* idle thread: 1
|
13
13
|
THREADS_IDLE_SCORE = 1
|
14
14
|
|
15
15
|
# Creates a new thread pool into which you can queue jobs.
|
@@ -24,6 +24,12 @@ module Threadz
|
|
24
24
|
# pool is checked. If there is more than one idle thread (and we're above minimum size), the
|
25
25
|
# kill score is incremented by THREADS_IDLE_SCORE for each idle thread. If there are no idle threads
|
26
26
|
# (and we're below maximum size) the kill score is decremented by THREADS_KILL_SCORE for each queued job.
|
27
|
+
# If the thread pool is being perfectly utilized (no queued work or idle workers), the kill score will decay
|
28
|
+
# and lose 10% of its value.
|
29
|
+
# In the default case of kill_threshold=10, if the thread pool is overworked for 10 consecutive checks (that is,
|
30
|
+
# 1 second), a new thread will be created and the counter reset. Similarly, if the thread pool is underutilized
|
31
|
+
# for 10 consecutive checks, an idle thread will be culled. If you want the thread pool to scale more quickly with
|
32
|
+
# demand, try lowering the kill_threshold value.
|
27
33
|
def initialize(opts={})
|
28
34
|
@min_size = opts[:initial_size] || 10 # documented
|
29
35
|
@max_size = opts[:maximum_size] || @min_size * 5 # documented
|
@@ -45,8 +51,9 @@ module Threadz
|
|
45
51
|
# Push a process onto the job queue for the thread pool to pick up.
|
46
52
|
# Note that using this method, you can't keep track of when the job
|
47
53
|
# finishes. If you care about when it finishes, use batches.
|
48
|
-
def process(&block)
|
49
|
-
|
54
|
+
def process(callback = nil, &block)
|
55
|
+
callback ||= block
|
56
|
+
@queue << callback
|
50
57
|
nil
|
51
58
|
end
|
52
59
|
|
@@ -110,10 +117,10 @@ module Threadz
|
|
110
117
|
@killscore > 0 ? kill_thread : spawn_thread
|
111
118
|
@killscore = 0
|
112
119
|
end
|
113
|
-
|
120
|
+
Threadz.dputs "killscore: #{@killscore}. waiting: #{@queue.num_waiting}. threads length: #{@worker_threads_count.value}. min/max: [#{@min_size}, #{@max_size}]"
|
114
121
|
sleep 0.1
|
115
122
|
end
|
116
123
|
end
|
117
124
|
end
|
118
125
|
end
|
119
|
-
end
|
126
|
+
end
|
data/spec/atomic_integer_spec.rb
CHANGED
@@ -7,16 +7,16 @@ describe Threadz do
|
|
7
7
|
# This test should always fail, but there is a small chance it won't...
|
8
8
|
|
9
9
|
i = 0
|
10
|
-
n =
|
11
|
-
threads =
|
10
|
+
n = 100_000
|
11
|
+
threads = 100
|
12
12
|
t = []
|
13
13
|
threads.times do
|
14
14
|
t << Thread.new do
|
15
|
-
sleep 0.
|
15
|
+
sleep 0.1
|
16
16
|
n.times { i += 1 }
|
17
17
|
end
|
18
18
|
t << Thread.new do
|
19
|
-
sleep 0.
|
19
|
+
sleep 0.1
|
20
20
|
n.times { i -= 1 }
|
21
21
|
end
|
22
22
|
end
|
data/spec/threadz_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe Threadz do
|
|
7
7
|
@T = Threadz::ThreadPool.new
|
8
8
|
end
|
9
9
|
|
10
|
-
it "should support process" do
|
10
|
+
it "should support process and accept a block" do
|
11
11
|
i = 0
|
12
12
|
3.times do
|
13
13
|
@T.process { i += 1}
|
@@ -17,12 +17,37 @@ describe Threadz do
|
|
17
17
|
i.should == 3
|
18
18
|
end
|
19
19
|
|
20
|
+
it "should support process and accept an arg that responds to :call" do
|
21
|
+
i = 0
|
22
|
+
3.times do
|
23
|
+
@T.process(Proc.new { i += 1} )
|
24
|
+
end
|
25
|
+
sleep 0.1
|
26
|
+
|
27
|
+
i.should == 3
|
28
|
+
end
|
29
|
+
|
20
30
|
it "should support creating batches" do
|
21
31
|
i = 0
|
22
32
|
|
23
33
|
lambda { @T.new_batch }.should_not raise_error
|
24
34
|
lambda { @T.new_batch(:latent => true) }.should_not raise_error
|
25
35
|
end
|
36
|
+
|
37
|
+
it "should not crash when killing threads" do
|
38
|
+
i = 0
|
39
|
+
b = @T.new_batch(:latent => true)
|
40
|
+
5000.times do
|
41
|
+
b << lambda { i += 1 }
|
42
|
+
b << lambda { i -= 1 }
|
43
|
+
b << [lambda { i += 2}, lambda { i -= 1}]
|
44
|
+
end
|
45
|
+
|
46
|
+
b.start
|
47
|
+
b.wait_until_done
|
48
|
+
|
49
|
+
50.times { sleep 0.1 }
|
50
|
+
end
|
26
51
|
|
27
52
|
describe Threadz::Batch do
|
28
53
|
it "should support jobs" do
|
@@ -195,4 +220,4 @@ describe Threadz do
|
|
195
220
|
end
|
196
221
|
end
|
197
222
|
end
|
198
|
-
end
|
223
|
+
end
|
data/threadz.gemspec
CHANGED
@@ -1,61 +1,22 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "threadz/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
9
|
-
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
s.
|
6
|
+
s.name = "threadz"
|
7
|
+
s.version = Threadz::VERSION
|
8
|
+
s.authors = ["Max Aller"]
|
9
|
+
s.email = ["nanodeath@gmail.com"]
|
10
|
+
s.homepage = "http://github.com/nanodeath/threadz"
|
11
|
+
s.summary = %q{An easy Ruby threadpool library.}
|
13
12
|
s.description = %q{A Ruby threadpool library to handle threadpools and make batch jobs easier.}
|
14
|
-
s.email = %q{nanodeath@gmail.com}
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"README.rdoc"
|
17
|
-
]
|
18
|
-
s.files = [
|
19
|
-
".gitignore",
|
20
|
-
"CHANGELOG",
|
21
|
-
"MIT-LICENSE",
|
22
|
-
"README.rdoc",
|
23
|
-
"Rakefile",
|
24
|
-
"VERSION",
|
25
|
-
"lib/threadz.rb",
|
26
|
-
"lib/threadz/atomic_integer.rb",
|
27
|
-
"lib/threadz/batch.rb",
|
28
|
-
"lib/threadz/directive.rb",
|
29
|
-
"lib/threadz/sleeper.rb",
|
30
|
-
"lib/threadz/thread_pool.rb",
|
31
|
-
"spec/atomic_integer_spec.rb",
|
32
|
-
"spec/basic/thread_pool_spec.rb",
|
33
|
-
"spec/performance/batch_spec.rb",
|
34
|
-
"spec/spec_helper.rb",
|
35
|
-
"spec/threadz_spec.rb",
|
36
|
-
"threadz.gemspec"
|
37
|
-
]
|
38
|
-
s.homepage = %q{http://github.com/nanodeath/threadz}
|
39
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
40
|
-
s.require_paths = ["lib"]
|
41
|
-
s.rubygems_version = %q{1.3.5}
|
42
|
-
s.summary = %q{An easy Ruby threadpool library.}
|
43
|
-
s.test_files = [
|
44
|
-
"spec/atomic_integer_spec.rb",
|
45
|
-
"spec/threadz_spec.rb",
|
46
|
-
"spec/performance/batch_spec.rb",
|
47
|
-
"spec/spec_helper.rb",
|
48
|
-
"spec/basic/thread_pool_spec.rb"
|
49
|
-
]
|
50
13
|
|
51
|
-
|
52
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
53
|
-
s.specification_version = 3
|
14
|
+
s.rubyforge_project = "threadz"
|
54
15
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
61
20
|
|
21
|
+
s.add_development_dependency "rspec", "~> 1.0"
|
22
|
+
end
|
metadata
CHANGED
@@ -1,76 +1,76 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: threadz
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.beta
|
5
|
+
prerelease: 6
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- Max Aller
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
date: 2011-12-22 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &74613530 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *74613530
|
16
25
|
description: A Ruby threadpool library to handle threadpools and make batch jobs easier.
|
17
|
-
email:
|
26
|
+
email:
|
27
|
+
- nanodeath@gmail.com
|
18
28
|
executables: []
|
19
|
-
|
20
29
|
extensions: []
|
21
|
-
|
22
|
-
|
23
|
-
- README.rdoc
|
24
|
-
files:
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
25
32
|
- .gitignore
|
26
33
|
- CHANGELOG
|
34
|
+
- Gemfile
|
35
|
+
- Gemfile.lock
|
27
36
|
- MIT-LICENSE
|
28
37
|
- README.rdoc
|
29
38
|
- Rakefile
|
30
|
-
- VERSION
|
31
39
|
- lib/threadz.rb
|
32
40
|
- lib/threadz/atomic_integer.rb
|
33
41
|
- lib/threadz/batch.rb
|
34
42
|
- lib/threadz/directive.rb
|
35
43
|
- lib/threadz/sleeper.rb
|
36
44
|
- lib/threadz/thread_pool.rb
|
45
|
+
- lib/threadz/version.rb
|
37
46
|
- spec/atomic_integer_spec.rb
|
38
47
|
- spec/basic/thread_pool_spec.rb
|
39
48
|
- spec/performance/batch_spec.rb
|
40
49
|
- spec/spec_helper.rb
|
41
50
|
- spec/threadz_spec.rb
|
42
51
|
- threadz.gemspec
|
43
|
-
has_rdoc: true
|
44
52
|
homepage: http://github.com/nanodeath/threadz
|
45
53
|
licenses: []
|
46
|
-
|
47
54
|
post_install_message:
|
48
|
-
rdoc_options:
|
49
|
-
|
50
|
-
require_paths:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
51
57
|
- lib
|
52
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>'
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.3.1
|
64
70
|
requirements: []
|
65
|
-
|
66
|
-
|
67
|
-
rubygems_version: 1.3.5
|
71
|
+
rubyforge_project: threadz
|
72
|
+
rubygems_version: 1.8.13
|
68
73
|
signing_key:
|
69
74
|
specification_version: 3
|
70
75
|
summary: An easy Ruby threadpool library.
|
71
|
-
test_files:
|
72
|
-
- spec/atomic_integer_spec.rb
|
73
|
-
- spec/threadz_spec.rb
|
74
|
-
- spec/performance/batch_spec.rb
|
75
|
-
- spec/spec_helper.rb
|
76
|
-
- spec/basic/thread_pool_spec.rb
|
76
|
+
test_files: []
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.1.3
|