ruby_thread_pool 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,59 @@
1
+ require "thread"
2
+
3
+ class ThreadPool
4
+ def initialize(pool_size)
5
+ @pool = []
6
+ @pool_size = pool_size
7
+ @pool_mutex = Mutex.new
8
+ @pool_cv = ConditionVariable.new
9
+ end
10
+
11
+ def run(*args)
12
+ Thread.new do
13
+ @pool_mutex.synchronize do
14
+ while @pool.size >= @pool_size
15
+ print "Pool is full: waiting to run #{args.join(",")}\n" if $DEBUG
16
+ @pool_cv.wait(@pool_mutex)
17
+ end
18
+ end
19
+ @pool << Thread.current
20
+ begin
21
+ yield(*args)
22
+ rescue => e
23
+ on_exception(self, e, *args)
24
+ ensure
25
+ @pool_mutex.synchronize do
26
+ @pool.delete(Thread.current)
27
+ @pool_cv.signal
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ alias_method :new, :run
34
+
35
+ def join
36
+ sleep 0.001 # needed because join must be called after threads
37
+ # had chance to lock
38
+ @pool_mutex.synchronize { @pool_cv.wait(@pool_mutex) until @pool.empty? }
39
+ end
40
+
41
+ def on_exception(thread, exception, *original_args)
42
+ # if you want to handle exception subclass and implement this method
43
+ end
44
+ end
45
+
46
+ class Array
47
+ def peach(size=nil, type=ThreadPool, &block)
48
+ if size == nil
49
+ threads = []
50
+ each { |*args| threads << Thread.new(*args, &block) }
51
+ threads.each {|t| t.join }
52
+ self
53
+ else
54
+ pool = type.new(size)
55
+ each { |*args| pool.new(*args, &block) }
56
+ pool.join
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,34 @@
1
+ require "minitest/autorun"
2
+ require_relative "../lib/thread_pool"
3
+
4
+ describe "ThreadPool" do
5
+ it "should wait for threads to finish" do
6
+ start = Time.now
7
+ 10.times.to_a.peach { sleep 0.1 }
8
+ stop = Time.now
9
+ time = stop - start
10
+ time.must_be :>=, 0.1
11
+ time.must_be :<=, 0.2
12
+ end
13
+
14
+ it "should run at max so many threads" do
15
+ start = Time.now
16
+ 20.times.to_a.peach(10) { sleep(0.1) }
17
+ stop = Time.now
18
+ time = stop - start
19
+ time.must_be :>=, 0.2
20
+ time.must_be :<=, 0.3
21
+ end
22
+
23
+ it "should not stop on long running threads" do
24
+ a = [0.01,0.01,0.2,0.2, 0.01, 0.01,0.01,0.01,0.01,0.01]
25
+ start = Time.now
26
+ a.peach(5) do |time|
27
+ sleep time
28
+ end
29
+ stop = Time.now
30
+ elapsed = stop - start
31
+ elapsed.must_be :>=, 0.2
32
+ elapsed.must_be :<=, 0.3
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_thread_pool
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jürgen Bickert
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-17 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: You can easily run number limited threads in parallel with ruby.
15
+ email: juergenbickert@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/thread_pool.rb
21
+ - spec/thread_pool_test.rb
22
+ homepage: http://juergenbickert.de
23
+ licenses: []
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements: []
42
+ rubyforge_project:
43
+ rubygems_version: 1.8.15
44
+ signing_key:
45
+ specification_version: 3
46
+ summary: A thread pool library for ruby.
47
+ test_files:
48
+ - spec/thread_pool_test.rb