Permalink
Browse files

Cleaned up build, switched to specs, restructured files and the same …

…three tests that were failing in test::unit are now failing in rspec in exactly the same way.

And I removed Loggable (there was no gemspec dep anyways) and have replaced it with simple Logger.
  • Loading branch information...
1 parent e531b78 commit c1a99b9b7d3a500d7ab08a5048b30328c1fdb283 @kaiwren committed Sep 17, 2009
Showing with 208 additions and 162 deletions.
  1. +2 −0 CHANGELOG
  2. +2 −0 README
  3. +29 −3 Rakefile
  4. +24 −58 lib/thread_pool.rb
  5. +11 −0 lib/thread_pool/completable.rb
  6. +33 −0 lib/thread_pool/executor.rb
  7. +6 −0 spec/spec.opts
  8. +4 −0 spec/spec_helper.rb
  9. +95 −0 spec/thread_pool_spec.rb
  10. +0 −99 test/test_thread_pool.rb
  11. +2 −2 thread_pool.gemspec
View
2 CHANGELOG
@@ -1,3 +1,5 @@
+Current
+- Moved to Rspec, added specs as default in build
0.3.1
- rescue Thread errors, use Loggable to print backtraces
0.3.0
View
2 README
@@ -1,3 +1,5 @@
+This is a fork of http://github.com/fizx/thread_pool
+_____________________
This code is still pretty early, and not yet used in production. That said, I am interested in feedback. You can send me a message on GitHub's internal messaging system ( http://github.com/inbox/new/fizx ).
A simple executor-style ThreadPool for Ruby (with tests, yay!)
View
32 Rakefile
@@ -1,3 +1,29 @@
-task :default do
- system "gem build thread_pool.gemspec; sudo gem uninstall thread_pool; sudo gem install thread_pool"
-end
+puts "Building on Ruby #{RUBY_VERSION}, #{RUBY_RELEASE_DATE}, #{RUBY_PLATFORM}"
+
+require 'rubygems'
+gem 'rspec', '>= 1.2.8'
+require 'rake'
+require 'spec'
+require 'spec/rake/spectask'
+
+
+desc 'Default: run spec tests.'
+task :default => :spec
+
+desc "Run all specs"
+Spec::Rake::SpecTask.new(:spec) do |task|
+ task.spec_files = FileList['spec/**/*_spec.rb']
+ task.spec_opts = ['--options', 'spec/spec.opts']
+end
+
+namespace :thread_pool do
+ desc "Build Gem"
+ task :build_gem do |task|
+ system "gem build thread_pool.gemspec;"
+ end
+
+ desc "Install Gem"
+ task :install_gem do |task|
+ system "sudo gem uninstall thread_pool; sudo gem install thread_pool"
+ end
+end
View
82 lib/thread_pool.rb
@@ -1,107 +1,73 @@
-# Hooray
+# Hooray
require "thread"
require "rubygems"
-require "loggable"
+require "logger"
+require "#{File.dirname(__FILE__)}/thread_pool/executor"
+require "#{File.dirname(__FILE__)}/thread_pool/completable"
class ThreadPool
- include Loggable
- class Executor
- include Loggable
- attr_reader :active
-
- def initialize(queue, mutex)
- @thread = Thread.new do
- loop do
- mutex.synchronize { @tuple = queue.shift }
- if @tuple
- debug "Executor: processing #{@tuple.hash}"
- args, block = @tuple
- @active = true
- begin
- block.call(*args)
- rescue Exception => e
- error e.message
- error e.backtrace.join("\n")
- end
- block.complete = true
- debug "Executor: complete #{@tuple.hash}"
- else
- @active = false
- sleep 0.01
- end
- end
- end
- end
-
- def close
- @thread.exit
- end
+ def self.logger=(logger)
+ @logger = logger
+ end
+
+ def self.logger
+ @logger
end
attr_accessor :queue_limit
-
+
# Initialize with number of threads to run
def initialize(count, queue_limit = 0)
@mutex = Mutex.new
@executors = []
@queue = []
@queue_limit = queue_limit
- @count = count
+ @count = count
count.times { @executors << Executor.new(@queue, @mutex) }
end
-
+
# Runs the block at some time in the near future
def execute(*args, &block)
init_completable(block)
-
+
if @queue_limit > 0
sleep 0.01 until @queue.size < @queue_limit
end
-
+
@mutex.synchronize do
@queue << [args, block]
end
end
-
- # Runs the block at some time in the near future, and blocks until complete
+
+ # Runs the block at some time in the near future, and blocks until complete
def synchronous_execute(*args, &block)
execute(*args, &block)
sleep 0.01 until block.complete?
end
-
+
# Size of the task queue
def waiting
@queue.size
end
-
+
# Size of the thread pool
def size
@count
end
-
+
# Kills all threads
def close
@executors.each {|e| e.close }
end
-
+
# Sleeps and blocks until the task queue is finished executing
def join
sleep 0.01 until @queue.empty? && @executors.all?{|e| !e.active}
end
-
-protected
+
+ protected
def init_completable(block)
block.extend(Completable)
block.complete = false
end
-
- module Completable
- def complete=(val)
- @complete = val
- end
-
- def complete?
- !!@complete
- end
- end
-end
+end
View
11 lib/thread_pool/completable.rb
@@ -0,0 +1,11 @@
+class ThreadPool
+ module Completable
+ def complete=(val)
+ @complete = val
+ end
+
+ def complete?
+ !!@complete
+ end
+ end
+end
View
33 lib/thread_pool/executor.rb
@@ -0,0 +1,33 @@
+class ThreadPool
+ class Executor
+ attr_reader :active
+
+ def initialize(queue, mutex)
+ @thread = Thread.new do
+ loop do
+ mutex.synchronize { @tuple = queue.shift }
+ if @tuple
+ ThreadPool.logger.debug "Executor: processing #{@tuple.hash}"
+ args, block = @tuple
+ @active = true
+ begin
+ block.call(*args)
+ rescue Exception => e
+ error e.message
+ error e.backtrace.join("\n")
+ end
+ block.complete = true
+ ThreadPool.logger.debug "Executor: complete #{@tuple.hash}"
+ else
+ @active = false
+ sleep 0.01
+ end
+ end
+ end
+ end
+
+ def close
+ @thread.exit
+ end
+ end
+end
View
6 spec/spec.opts
@@ -0,0 +1,6 @@
+--colour
+--format
+specdoc
+--loadby
+mtime
+--reverse
View
4 spec/spec_helper.rb
@@ -0,0 +1,4 @@
+require File.expand_path(File.dirname(__FILE__) + "/../lib/thread_pool")
+require 'spec'
+
+ThreadPool.logger = Logger.new(STDOUT)
View
95 spec/thread_pool_spec.rb
@@ -0,0 +1,95 @@
+require "test/unit"
+require "timeout"
+require File.dirname(__FILE__) + "/../lib/thread_pool"
+
+describe ThreadPool do
+ THREADS = 10
+
+ before :each do
+ @pool = ThreadPool.new(THREADS)
+ end
+
+ after :each do
+ @pool.close
+ end
+
+ it 'test_pool_size' do
+ @pool.size.should == THREADS
+ end
+
+ it 'test_waiting' do
+ n = 50
+ n.times {
+ @pool.execute { sleep 10 }
+ }
+ sleep 0.01
+ @pool.waiting.should == (n - THREADS)
+ end
+
+ class A
+ def initialize(i)
+ @i = i
+ end
+ attr_reader :i
+ end
+
+ it 'test_context' do
+ foo = []
+ bar = (0...5).to_a
+ while c = bar.shift
+ @pool.execute { foo << c }
+ end
+ @pool.join
+ foo.should == [nil] * 5
+
+ foo = []
+ bar = (0...5).to_a
+ while c = bar.shift
+ @pool.execute(c) {|n| foo << n }
+ end
+ @pool.join
+ foo.should == (0...5).to_a
+ end
+
+ it 'test_queue_limit' do
+ n = 50
+ foo = 0
+ @pool.queue_limit = 1
+ begin
+ Timeout::timeout(0.2) do
+ n.times {
+ @pool.execute { sleep 1 }
+ foo += 1
+ }
+ end
+ rescue Timeout::Error
+ (@pool.queue_limit + @pool.size).should == foo
+ else
+ fail
+ end
+ end
+
+ it 'test_execution' do
+ Timeout::timeout(1) do
+ n = 50
+ foo = []
+ n.times {
+ @pool.execute { foo << "hi" }
+ }
+ @pool.join
+ foo.length.should == n
+ end
+ end
+
+ it 'test_synchronous_execute' do
+ Timeout::timeout(1) do
+ foo = false
+ @pool.execute { sleep 0.01; foo = true }
+ foo.should be_false
+
+ foo = false
+ @pool.synchronous_execute { sleep 0.01; foo = true }
+ foo.should be_true
+ end
+ end
+end
View
99 test/test_thread_pool.rb
@@ -1,99 +0,0 @@
-require "test/unit"
-require "timeout"
-require File.dirname(__FILE__) + "/../lib/thread_pool"
-
-class TestThreadPool < Test::Unit::TestCase
- THREADS = 10
-
- def setup
- @pool = ThreadPool.new(THREADS)
- end
-
- def teardown
- @pool.close
- end
-
- def test_creation
- #implicit
- end
-
- def test_pool_size
- assert_equal THREADS, @pool.size
- end
-
- def test_waiting
- n = 50
- n.times {
- @pool.execute { sleep 10 }
- }
- sleep 0.01
- assert_equal n - THREADS, @pool.waiting
- end
-
- class A
- def initialize(i)
- @i = i
- end
- attr_reader :i
- end
-
- def test_context
- @foo = []
- @bar = (0...5).to_a
- while c = @bar.shift
- @pool.execute { @foo << c }
- end
- @pool.join
- assert_equal [nil] * 5, @foo
-
- @foo = []
- @bar = (0...5).to_a
- while c = @bar.shift
- @pool.execute(c) {|n| @foo << n }
- end
- @pool.join
- assert_equal (0...5).to_a, @foo
- end
-
- def test_queue_limit
- n = 50
- @foo = 0
- @pool.queue_limit = 1
- begin
- Timeout::timeout(0.2) do
- n.times {
- @pool.execute { sleep 1 }
- @foo += 1
- }
- end
- rescue Timeout::Error
- assert_equal @pool.queue_limit + @pool.size, @foo
- else
- assert false
- end
- end
-
- def test_execution
- Timeout::timeout(1) do
- n = 50
- @foo = []
- n.times {
- @pool.execute { @foo << "hi" }
- }
- @pool.join
- assert_equal n, @foo.length
- end
- end
-
- def test_synchronous_execute
- Timeout::timeout(1) do
- @foo = false
- @pool.execute { sleep 0.01; @foo = true }
- assert !@foo
-
- @foo = false
- @pool.synchronous_execute { sleep 0.01; @foo = true }
- assert @foo
- end
- end
-end
View
4 thread_pool.gemspec
@@ -4,10 +4,10 @@ Gem::Specification.new do |s|
s.date = "2008-09-24"
s.summary = "A ruby thread pool"
s.email = "kyle@kylemaxwell.com"
- s.homepage = "http://github.com/fizx/thread_pool"
+ s.homepage = "http://github.com/kaiwren/thread_pool"
s.description = "A simple thread pool"
s.has_rdoc = true
- s.authors = ["Kyle Maxwell"]
+ s.authors = ["Kyle Maxwell", "Sidu Ponnappa"]
s.files = %w[
README CHANGELOG lib/thread_pool.rb
]

0 comments on commit c1a99b9

Please sign in to comment.