thread-pool 0.0.1

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/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
+