[DRE-commits] [ruby-threach] 01/03: Imported Upstream version 0.2.0

Michael Crusoe misterc-guest at moszumanska.debian.org
Sat Oct 3 05:15:30 UTC 2015


This is an automated email from the git hooks/post-receive script.

misterc-guest pushed a commit to branch master
in repository ruby-threach.

commit f5143c50026ff78e05ceb48c06c688a0c4c7d00e
Author: Michael R. Crusoe <michael.crusoe at gmail.com>
Date:   Sun Sep 20 00:27:05 2015 -0700

    Imported Upstream version 0.2.0
---
 .document                                  |   5 ++
 .gitignore                                 |  21 +++++
 LICENSE                                    |  20 +++++
 README.markdown                            | 102 ++++++++++++++++++++++++
 Rakefile                                   |  65 ++++++++++++++++
 VERSION                                    |   1 +
 features/step_definitions/threach_steps.rb |   0
 features/support/env.rb                    |   6 ++
 features/threach.feature                   |   9 +++
 lib/threach.rb                             |  35 +++++++++
 metadata.yml                               | 121 +++++++++++++++++++++++++++++
 test/helper.rb                             |  10 +++
 test/test_threach.rb                       |   7 ++
 13 files changed, 402 insertions(+)

diff --git a/.document b/.document
new file mode 100644
index 0000000..ecf3673
--- /dev/null
+++ b/.document
@@ -0,0 +1,5 @@
+README.rdoc
+lib/**/*.rb
+bin/*
+features/**/*.feature
+LICENSE
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c1e0daf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+## MAC OS
+.DS_Store
+
+## TEXTMATE
+*.tmproj
+tmtags
+
+## EMACS
+*~
+\#*
+.\#*
+
+## VIM
+*.swp
+
+## PROJECT::GENERAL
+coverage
+rdoc
+pkg
+
+## PROJECT::SPECIFIC
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0f91819
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 Bill Dueber
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.markdown b/README.markdown
new file mode 100644
index 0000000..02eb76b
--- /dev/null
+++ b/README.markdown
@@ -0,0 +1,102 @@
+# threach
+
+`threach` adds to the Enumerable module to provide a threaded
+version of whatever enumerator you throw at it (`each` by default).
+
+## Warning: Deadlocks under JRuby if an exception is thrown
+
+`threach` works fine, so long as nothing goes wrong. In particular, there's no safe way (that I can find; see below) to break out of a `threach` loop without a deadlock under JRuby. This is, shall we say, an Issue. 
+
+Under vanilla ruby, `threach` will exit as expected, but who the hell wants to 
+use `threach` where there are no real threads???
+
+## Installation
+
+`threach` is on rubygems.org, so you should just be able to do
+
+    gem install threach
+    # or jruby -S gem install threach
+
+## Use
+
+    # You like #each? You'll love...err.."probably like" #threach
+    require 'rubygems'
+    require 'threach'
+    
+    # Process with 2 threads. It assumes you want 'each'
+    # as your iterator.
+    (1..10).threach(2) {|i| puts i.to_s}  
+
+    # You can also specify the iterator
+    File.open('mybigfile') do |f|
+      f.threach(2, :each_line) do |line|
+        processLine(line)
+      end
+    end
+
+    # threach does not care what the arity of your block is
+    # as long as it matches the iterator you ask for
+
+    ('A'..'Z').threach(3, :each_with_index) do |letter, index|
+      puts "#{index}: #{letter}"
+    end
+
+    # Or with a hash
+    h = {'a' => 1, 'b'=>2, 'c'=>3}
+    h.threach(2) do |letter, i|
+      puts "#{i}: #{letter}"
+    end
+
+## Major problem
+
+I can't figure out how to exit gracefully from a threach loop. 
+
+  begin
+    ('a'..'z').threach(2, :each_with_index) do |letter, i|
+      break if i > 10  # will deadlock under jruby; fine under ruby
+      # raise StandardError if i > 10 # deadlock under jruby; find under ruby
+      puts letter
+    end
+  rescue 
+    puts "Rescued; broke out of the loop"
+  end
+
+The `break` under jruby prints "Exception in thread "Thread-1" org.jruby.exceptions.JumpException$BreakJump," but if there's a way to catch that in the enclosing code I sure don't know how. 
+
+Use of `catch` and `throw` seemed like an obvious choice, but they don't work across threads. Then I thought I'd use `catch` within the consumers and throw or raise an error at the producer, but that doesn't work, either. 
+
+I'm clearly up against (or well beyond) my knowledge limitations, here.
+
+If anyone has a solution to what should be a simple problem (and works under both ruby and jruby) boy, would I be grateful.
+
+## Why and when to use it?
+
+Well, if you're using stock (MRI) ruby -- you probably shouldn't bother with `threach`. It'll just slow things down. But if you're using a ruby implementation that has real threads, like JRuby, this will give you relatively painless multi-threading.
+
+You can always do something like:
+
+    if defined? JRUBY_VERSION
+      numthreads = 3
+    else
+      numthreads = 0
+    end
+
+    my_enumerable.threach(numthreads) {|i| ...}
+
+Note the "relatively" in front of "painless" up there. The block you pass still has to be thread-safe, and there are many data structures you'll encounter that are *not* thread-safe. Scalars, arrays, and hashes are, though, under JRuby, and that'll get you pretty far.
+
+
+
+## Note on Patches/Pull Requests
+ 
+* Fork the project.
+* Make your feature addition or bug fix.
+* Add tests for it. This is important so I don't break it in a
+  future version unintentionally.
+* Commit, do not mess with rakefile, version, or history.
+  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
+* Send me a pull request. Bonus points for topic branches.
+
+## Copyright
+
+Copyright (c) 2010 Bill Dueber. See LICENSE for details.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..16ddb18
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,65 @@
+require 'rubygems'
+require 'rake'
+
+begin
+  require 'jeweler'
+  Jeweler::Tasks.new do |gem|
+    gem.name = "threach"
+    gem.summary = %Q{Threaded each}
+    gem.description = %Q{An addition to the Enumerable module that allows easy use of threaded each and each-like iterators}
+    gem.email = "bill at dueber.com"
+    gem.homepage = "http://github.com/billdueber/threach"
+    gem.authors = ["Bill Dueber"]
+    gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
+    gem.add_development_dependency "yard", ">= 0"
+    gem.add_development_dependency "cucumber", ">= 0"
+    # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
+  end
+  Jeweler::GemcutterTasks.new
+rescue LoadError
+  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
+end
+
+require 'rake/testtask'
+Rake::TestTask.new(:test) do |test|
+  test.libs << 'lib' << 'test'
+  test.pattern = 'test/**/test_*.rb'
+  test.verbose = true
+end
+
+begin
+  require 'rcov/rcovtask'
+  Rcov::RcovTask.new do |test|
+    test.libs << 'test'
+    test.pattern = 'test/**/test_*.rb'
+    test.verbose = true
+  end
+rescue LoadError
+  task :rcov do
+    abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
+  end
+end
+
+task :test => :check_dependencies
+
+begin
+  require 'cucumber/rake/task'
+  Cucumber::Rake::Task.new(:features)
+
+  task :features => :check_dependencies
+rescue LoadError
+  task :features do
+    abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
+  end
+end
+
+task :default => :test
+
+begin
+  require 'yard'
+  YARD::Rake::YardocTask.new
+rescue LoadError
+  task :yardoc do
+    abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
+  end
+end
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..0ea3a94
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.2.0
diff --git a/features/step_definitions/threach_steps.rb b/features/step_definitions/threach_steps.rb
new file mode 100644
index 0000000..e69de29
diff --git a/features/support/env.rb b/features/support/env.rb
new file mode 100644
index 0000000..a1bbd24
--- /dev/null
+++ b/features/support/env.rb
@@ -0,0 +1,6 @@
+$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
+require 'threach'
+
+require 'test/unit/assertions'
+
+World(Test::Unit::Assertions)
diff --git a/features/threach.feature b/features/threach.feature
new file mode 100644
index 0000000..b908b60
--- /dev/null
+++ b/features/threach.feature
@@ -0,0 +1,9 @@
+Feature: something something
+  In order to something something
+  A user something something
+  something something something
+
+  Scenario: something something
+    Given inspiration
+    When I create a sweet new gem
+    Then everyone should see how awesome I am
diff --git a/lib/threach.rb b/lib/threach.rb
new file mode 100644
index 0000000..809a9a0
--- /dev/null
+++ b/lib/threach.rb
@@ -0,0 +1,35 @@
+require 'thread'
+module Enumerable
+  
+  def threach(threads=0, iterator=:each, &blk)
+    if threads == 0
+      self.send(iterator) do |*args|
+        blk.call *args
+      end
+    else
+      bq = SizedQueue.new(threads * 2)
+      consumers = []
+      threads.times do |i|
+        consumers << Thread.new(i) do |i|
+          until (a = bq.pop) === :end_of_data
+            blk.call(*a)
+          end
+        end          
+      end
+    
+      # The producer
+      count = 0
+      self.send(iterator) do |*x|
+        bq.push x
+        count += 1
+      end
+      # Now end it
+      threads.times do 
+        bq << :end_of_data
+      end
+      # Do the join
+      consumers.each {|t| t.join}
+    end
+  end
+    
+end
diff --git a/metadata.yml b/metadata.yml
new file mode 100644
index 0000000..fb111f0
--- /dev/null
+++ b/metadata.yml
@@ -0,0 +1,121 @@
+--- !ruby/object:Gem::Specification 
+name: threach
+version: !ruby/object:Gem::Version 
+  hash: 23
+  prerelease: false
+  segments: 
+  - 0
+  - 2
+  - 0
+  version: 0.2.0
+platform: ruby
+authors: 
+- Bill Dueber
+autorequire: 
+bindir: bin
+cert_chain: []
+
+date: 2010-08-10 00:00:00 -04:00
+default_executable: 
+dependencies: 
+- !ruby/object:Gem::Dependency 
+  name: thoughtbot-shoulda
+  prerelease: false
+  requirement: &id001 !ruby/object:Gem::Requirement 
+    none: false
+    requirements: 
+    - - ">="
+      - !ruby/object:Gem::Version 
+        hash: 3
+        segments: 
+        - 0
+        version: "0"
+  type: :development
+  version_requirements: *id001
+- !ruby/object:Gem::Dependency 
+  name: yard
+  prerelease: false
+  requirement: &id002 !ruby/object:Gem::Requirement 
+    none: false
+    requirements: 
+    - - ">="
+      - !ruby/object:Gem::Version 
+        hash: 3
+        segments: 
+        - 0
+        version: "0"
+  type: :development
+  version_requirements: *id002
+- !ruby/object:Gem::Dependency 
+  name: cucumber
+  prerelease: false
+  requirement: &id003 !ruby/object:Gem::Requirement 
+    none: false
+    requirements: 
+    - - ">="
+      - !ruby/object:Gem::Version 
+        hash: 3
+        segments: 
+        - 0
+        version: "0"
+  type: :development
+  version_requirements: *id003
+description: An addition to the Enumerable module that allows easy use of threaded each and each-like iterators
+email: bill at dueber.com
+executables: []
+
+extensions: []
+
+extra_rdoc_files: 
+- LICENSE
+- README.markdown
+files: 
+- .document
+- .gitignore
+- LICENSE
+- README.markdown
+- Rakefile
+- VERSION
+- features/step_definitions/threach_steps.rb
+- features/support/env.rb
+- features/threach.feature
+- lib/threach.rb
+- test/helper.rb
+- test/test_threach.rb
+has_rdoc: true
+homepage: http://github.com/billdueber/threach
+licenses: []
+
+post_install_message: 
+rdoc_options: 
+- --charset=UTF-8
+require_paths: 
+- lib
+required_ruby_version: !ruby/object:Gem::Requirement 
+  none: false
+  requirements: 
+  - - ">="
+    - !ruby/object:Gem::Version 
+      hash: 3
+      segments: 
+      - 0
+      version: "0"
+required_rubygems_version: !ruby/object:Gem::Requirement 
+  none: false
+  requirements: 
+  - - ">="
+    - !ruby/object:Gem::Version 
+      hash: 3
+      segments: 
+      - 0
+      version: "0"
+requirements: []
+
+rubyforge_project: 
+rubygems_version: 1.3.7
+signing_key: 
+specification_version: 3
+summary: Threaded each
+test_files: 
+- test/helper.rb
+- test/test_threach.rb
diff --git a/test/helper.rb b/test/helper.rb
new file mode 100644
index 0000000..953e56a
--- /dev/null
+++ b/test/helper.rb
@@ -0,0 +1,10 @@
+require 'rubygems'
+require 'test/unit'
+require 'shoulda'
+
+$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+$LOAD_PATH.unshift(File.dirname(__FILE__))
+require 'threach'
+
+class Test::Unit::TestCase
+end
diff --git a/test/test_threach.rb b/test/test_threach.rb
new file mode 100644
index 0000000..e9e0621
--- /dev/null
+++ b/test/test_threach.rb
@@ -0,0 +1,7 @@
+require 'helper'
+
+class TestThreach < Test::Unit::TestCase
+  should "probably rename this file and start testing for real" do
+    flunk "hey buddy, you should probably rename this file and start testing for real"
+  end
+end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-threach.git



More information about the Pkg-ruby-extras-commits mailing list