thread-pool 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc ADDED
@@ -0,0 +1,4 @@
1
+
2
+ === 0.0.1 / YYYY-MM-DD
3
+
4
+ * Initial release
data/Manifest ADDED
@@ -0,0 +1,15 @@
1
+ History.rdoc
2
+ Manifest
3
+ README.rdoc
4
+ Rakefile
5
+ examples/basic.rb
6
+ examples/timeout.rb
7
+ lib/thread-pool.rb
8
+ lib/thread-pool/pool.rb
9
+ lib/thread-pool/version.rb
10
+ spec/GEM_spec.rb
11
+ spec/spec_helper.rb
12
+ tasks/docs.rake
13
+ tasks/gemspec.rake
14
+ tasks/spec.rake
15
+ thread-pool.gemspec
data/README.rdoc ADDED
@@ -0,0 +1,29 @@
1
+
2
+ = Thread Pool
3
+
4
+ Multi-threaded Array subclass.
5
+
6
+ == License:
7
+
8
+ (The MIT License)
9
+
10
+ Copyright (c) 2009 TJ Holowaychuk <tj@vision-media.ca>
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining
13
+ a copy of this software and associated documentation files (the
14
+ 'Software'), to deal in the Software without restriction, including
15
+ without limitation the rights to use, copy, modify, merge, publish,
16
+ distribute, sublicense, an d/or sell copies of the Software, and to
17
+ permit persons to whom the Software is furnished to do so, subject to
18
+ the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be
21
+ included in all copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
24
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+
2
+ $:.unshift 'lib'
3
+ require 'thread-pool'
4
+ require 'rubygems'
5
+ require 'rake'
6
+ require 'echoe'
7
+
8
+ Echoe.new "thread-pool", ThreadPool::VERSION do |p|
9
+ p.author = "TJ Holowaychuk"
10
+ p.email = "tj@vision-media.ca"
11
+ p.summary = "Multi-threaded Array subclass"
12
+ p.runtime_dependencies = []
13
+ end
14
+
15
+ Dir['tasks/**/*.rake'].sort.each { |f| load f }
data/examples/basic.rb ADDED
@@ -0,0 +1,71 @@
1
+
2
+ $:.unshift File.dirname(__FILE__) + '/../lib'
3
+ require 'thread-pool'
4
+
5
+ # TODO: thread-safe ThreadPool ? ensure all methods are thread safe
6
+ # TODO: fix issue with joining threads as they are added ...
7
+ # sleep 0.002 while busy?
8
+ # TODO: get stop to work
9
+ # TODO: hard stop! ? resume?
10
+ # TODO: stop
11
+ # TODO: stop! kill terminate
12
+
13
+ # Any object responding to #call may be passed to #<<
14
+
15
+ pool = ThreadPool.new 2
16
+ pool << lambda { sleep 0.5; puts 'one' }
17
+ pool << lambda { sleep 0.5; puts 'two' }
18
+ pool << lambda { sleep 0.5; puts 'three' }
19
+ pool << lambda { sleep 0.5; puts 'four' }
20
+ pool << lambda { sleep 0.5; puts 'five' }
21
+ pool.join
22
+ p pool
23
+
24
+ # Calling #process on a pool will push the given
25
+ # block onto the queue. Arguments may be passed as parameters into
26
+ # the thread.
27
+
28
+ pool = ThreadPool.new
29
+ 1.upto(10) do |n|
30
+ pool.process(n * 2) { |n|
31
+ sleep 0.5
32
+ p n
33
+ }
34
+ end
35
+ pool.join
36
+ p pool
37
+
38
+ # You may specify the :reap_interval which reaps old threads.
39
+
40
+ ThreadPool.new 5, :reap_interval => 0.0002 do |pool|
41
+ 1.upto(10) do |n|
42
+ pool.process(n) { |n|
43
+ sleep 0.5
44
+ p n
45
+ }
46
+ end
47
+ end
48
+ p pool
49
+
50
+ # A block may be passed to #new which then calls #join at the end.
51
+
52
+ ThreadPool.new do
53
+ 1.upto(10) do |n|
54
+ process(n) { |n|
55
+ sleep 0.5
56
+ p n
57
+ }
58
+ end
59
+ end
60
+ p pool
61
+
62
+ # Another example
63
+
64
+ ThreadPool.new do |pool|
65
+ 1.upto(50) do |n|
66
+ pool << lambda { p n }
67
+ pool.stop if n > 30
68
+ end
69
+ end
70
+ p pool
71
+
File without changes
@@ -0,0 +1,25 @@
1
+ #--
2
+ # Copyright (c) 2009 TJ Holowaychuk <tj@vision-media.ca>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require 'thread-pool/version'
25
+ require 'thread-pool/pool'
@@ -0,0 +1,156 @@
1
+
2
+ class ThreadPool
3
+
4
+ #--
5
+ # Constants
6
+ #++
7
+
8
+ ##
9
+ # Max number of worker threads available to this pool.
10
+
11
+ THREAD_LIMIT = 10
12
+
13
+ ##
14
+ # Interval at which to poll the workers, at which time
15
+ # any inactive threads are destroyed.
16
+
17
+ REAP_INTERVAL = 0.002
18
+
19
+ ##
20
+ # Interval at which to poll workers, preventing the
21
+ # parent thread from exiting.
22
+
23
+ JOIN_INTERVAL = 0.002
24
+
25
+ ##
26
+ # Live threads.
27
+
28
+ attr_reader :threads
29
+
30
+ ##
31
+ # Maximum threads.
32
+
33
+ attr_reader :max_threads
34
+
35
+ ##
36
+ # Reap interval.
37
+
38
+ attr_reader :reap_interval
39
+
40
+ ##
41
+ # Initialize with _max_threads_ and _options_.
42
+ # When a _block_ is passed it will be evaluated in context
43
+ # to the thread pool, or the thread pool will be yielded, and
44
+ # the pool will call #join before exiting the block.
45
+ #
46
+ # === Options
47
+ #
48
+ # :reap_interval reap interval or REAP_INTERVAL
49
+ #
50
+
51
+ def initialize max_threads = nil, options = {}, &block
52
+ @threads, @data = [], []
53
+ @max_threads = max_threads || THREAD_LIMIT
54
+ @reap_interval = options.fetch :reap_interval, REAP_INTERVAL
55
+ if block
56
+ if block.arity > 0
57
+ yield self
58
+ else
59
+ self.instance_eval &block
60
+ end
61
+ join
62
+ end
63
+ end
64
+
65
+ ##
66
+ # Process any _object_ which must respond to #call in a worker thread.
67
+
68
+ def << object
69
+ process &lambda { |*args|
70
+ object.call *args
71
+ }
72
+ end
73
+
74
+ ##
75
+ # Fetch a worker and execute _block_ passing _args_.
76
+
77
+ def process *args, &block
78
+ @data << [args, block]
79
+ end
80
+
81
+ ##
82
+ # Return inspection string.
83
+
84
+ def inspect
85
+ "#<ThreadPool:#{__id__} max_threads:#{max_threads} threads:#{threads.length}>"
86
+ end
87
+
88
+ ##
89
+ # Run worker thread with _args_ and _block_.
90
+
91
+ def worker *args, &block
92
+ unless threads.length > max_threads
93
+ threads << Thread.new(*args, &block)
94
+ else
95
+ sleep REAP_INTERVAL
96
+ reap; retry
97
+ end
98
+ end
99
+
100
+ ##
101
+ # Run workers.
102
+
103
+ def start
104
+ @running = true
105
+ @data.each do |args, proc|
106
+ worker *args, &proc
107
+ end
108
+ end
109
+
110
+ ##
111
+ # Stop the thread pool, killing its workers.
112
+
113
+ def stop
114
+ threads.each do |thread|
115
+ thread.kill
116
+ end
117
+ @running = false
118
+ end
119
+
120
+ ##
121
+ # Check if the thread pool is running.
122
+
123
+ def running?
124
+ @running
125
+ end
126
+
127
+ ##
128
+ # Check if any thread pool workers are busy.
129
+
130
+ def busy?
131
+ running? && threads.any? { |thread| thread.alive? }
132
+ end
133
+
134
+ ##
135
+ # Join threads and start workers.
136
+
137
+ def join
138
+ start unless running?
139
+ sleep JOIN_INTERVAL while busy?
140
+ end
141
+
142
+ private
143
+
144
+ ##
145
+ # Reap dead threads.
146
+
147
+ def reap
148
+ threads.delete_if do |thread|
149
+ not thread.alive?
150
+ end.each do |thread|
151
+ thread.kill
152
+ end
153
+ end
154
+
155
+ end
156
+
@@ -0,0 +1,4 @@
1
+
2
+ class ThreadPool < Array
3
+ VERSION = '0.0.1'
4
+ end
data/spec/GEM_spec.rb ADDED
File without changes
File without changes
data/tasks/docs.rake ADDED
@@ -0,0 +1,13 @@
1
+
2
+ namespace :docs do
3
+
4
+ desc 'Remove rdoc products'
5
+ task :remove => [:clobber_docs]
6
+
7
+ desc 'Build docs, and open in browser for viewing (specify BROWSER)'
8
+ task :open do
9
+ browser = ENV["BROWSER"] || "safari"
10
+ sh "open -a #{browser} doc/index.html"
11
+ end
12
+
13
+ end
@@ -0,0 +1,3 @@
1
+
2
+ desc 'Build gemspec file'
3
+ task :gemspec => [:build_gemspec]
data/tasks/spec.rake ADDED
@@ -0,0 +1,25 @@
1
+
2
+ require 'spec/rake/spectask'
3
+
4
+ desc "Run all specifications"
5
+ Spec::Rake::SpecTask.new(:spec) do |t|
6
+ t.libs << "lib"
7
+ t.spec_opts = ["--color", "--require", "spec/spec_helper.rb"]
8
+ end
9
+
10
+ namespace :spec do
11
+
12
+ desc "Run all specifications verbosely"
13
+ Spec::Rake::SpecTask.new(:verbose) do |t|
14
+ t.libs << "lib"
15
+ t.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
16
+ end
17
+
18
+ desc "Run specific specification verbosely (specify SPEC)"
19
+ Spec::Rake::SpecTask.new(:select) do |t|
20
+ t.libs << "lib"
21
+ t.spec_files = [ENV["SPEC"]]
22
+ t.spec_opts = ["--color", "--format", "specdoc", "--require", "spec/spec_helper.rb"]
23
+ end
24
+
25
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{thread-pool}
5
+ s.version = "0.0.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["TJ Holowaychuk"]
9
+ s.date = %q{2009-10-12}
10
+ s.description = %q{Multi-threaded Array subclass}
11
+ s.email = %q{tj@vision-media.ca}
12
+ s.extra_rdoc_files = ["README.rdoc", "lib/thread-pool.rb", "lib/thread-pool/pool.rb", "lib/thread-pool/version.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
13
+ s.files = ["History.rdoc", "Manifest", "README.rdoc", "Rakefile", "examples/basic.rb", "examples/timeout.rb", "lib/thread-pool.rb", "lib/thread-pool/pool.rb", "lib/thread-pool/version.rb", "spec/GEM_spec.rb", "spec/spec_helper.rb", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake", "thread-pool.gemspec"]
14
+ s.homepage = %q{}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Thread-pool", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{thread-pool}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{Multi-threaded Array subclass}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: thread-pool
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - TJ Holowaychuk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-12 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Multi-threaded Array subclass
17
+ email: tj@vision-media.ca
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ - lib/thread-pool.rb
25
+ - lib/thread-pool/pool.rb
26
+ - lib/thread-pool/version.rb
27
+ - tasks/docs.rake
28
+ - tasks/gemspec.rake
29
+ - tasks/spec.rake
30
+ files:
31
+ - History.rdoc
32
+ - Manifest
33
+ - README.rdoc
34
+ - Rakefile
35
+ - examples/basic.rb
36
+ - examples/timeout.rb
37
+ - lib/thread-pool.rb
38
+ - lib/thread-pool/pool.rb
39
+ - lib/thread-pool/version.rb
40
+ - spec/GEM_spec.rb
41
+ - spec/spec_helper.rb
42
+ - tasks/docs.rake
43
+ - tasks/gemspec.rake
44
+ - tasks/spec.rake
45
+ - thread-pool.gemspec
46
+ has_rdoc: true
47
+ homepage: ""
48
+ licenses: []
49
+
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --line-numbers
53
+ - --inline-source
54
+ - --title
55
+ - Thread-pool
56
+ - --main
57
+ - README.rdoc
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "1.2"
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project: thread-pool
75
+ rubygems_version: 1.3.5
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Multi-threaded Array subclass
79
+ test_files: []
80
+