threadify 0.0.3 → 1.0.0

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/README CHANGED
@@ -16,7 +16,7 @@ URI
16
16
  http://rubyforge.org/projects/codeforpeople
17
17
 
18
18
  SAMPLES
19
-
19
+
20
20
  <========< sample/a.rb >========>
21
21
 
22
22
  ~ > cat sample/a.rb
@@ -66,10 +66,22 @@ SAMPLES
66
66
 
67
67
  ~ > ruby sample/a.rb
68
68
 
69
+ /opt/local/lib/ruby/1.8/net/http.rb:560:in `initialize': getaddrinfo: nodename nor servname provided, or not known (SocketError)
70
+ from /opt/local/lib/ruby/1.8/net/http.rb:560:in `open'
71
+ from /opt/local/lib/ruby/1.8/net/http.rb:560:in `connect'
72
+ from /opt/local/lib/ruby/1.8/timeout.rb:48:in `timeout'
73
+ from /opt/local/lib/ruby/1.8/timeout.rb:76:in `timeout'
74
+ from /opt/local/lib/ruby/1.8/net/http.rb:560:in `connect'
75
+ from /opt/local/lib/ruby/1.8/net/http.rb:553:in `do_start'
76
+ from /opt/local/lib/ruby/1.8/net/http.rb:542:in `start'
77
+ from /opt/local/lib/ruby/1.8/open-uri.rb:242:in `open_http'
78
+ ... 8 levels...
79
+ from sample/a.rb:21:in `each'
80
+ from sample/a.rb:21
81
+ from sample/a.rb:37:in `time'
82
+ from sample/a.rb:20
69
83
  ---
70
- without threadify: 3.75206303596497
71
- ---
72
- with threadify: 1.37899804115295
84
+ without threadify: 0.0373568534851074
73
85
 
74
86
 
75
87
  <========< sample/b.rb >========>
@@ -113,16 +125,20 @@ SAMPLES
113
125
  ~ > ruby sample/b.rb
114
126
 
115
127
  ---
116
- without threadify: 0.00630998611450195
128
+ without threadify: 0.00681805610656738
117
129
  ---
118
- with threadify: 0.270262956619263
130
+ with threadify: 0.57867693901062
119
131
  ---
120
132
  :needle: 21844
121
133
  :a: 21844
122
134
  :b: 21844
123
135
 
124
136
 
137
+
125
138
  HISTORY
139
+ 1.0.0
140
+ - adjust threadify to yield objects exactly like Enumerable#each
141
+
126
142
  0.0.3
127
143
  - added ability to short-circuit the parallel processing, a.k.a to 'break'
128
144
  from threadify
data/README.rb ADDED
@@ -0,0 +1,83 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ template = <<-__
4
+ NAME
5
+ threadify.rb
6
+
7
+ SYNOPSIS
8
+ enumerable = %w( a b c d )
9
+ enumerable.threadify(2){ 'process this block using two worker threads' }
10
+
11
+ DESCRIPTION
12
+ threadify.rb makes it stupid easy to process a bunch of data using 'n'
13
+ worker threads
14
+
15
+ INSTALL
16
+ gem install threadify
17
+
18
+ URI
19
+ http://rubyforge.org/projects/codeforpeople
20
+
21
+ SAMPLES
22
+ <%= samples %>
23
+
24
+ HISTORY
25
+ 1.0.0
26
+ - adjust threadify to yield objects exactly like Enumerable#each
27
+
28
+ 0.0.3
29
+ - added ability to short-circuit the parallel processing, a.k.a to 'break'
30
+ from threadify
31
+
32
+ 0.0.2
33
+ - don't use thread.exit, just let the thread die naturally
34
+ - add version to Threadify module
35
+ - comments ;-)
36
+ __
37
+
38
+
39
+ require 'erb'
40
+ require 'pathname'
41
+
42
+ $VERBOSE=nil
43
+
44
+ def indent(s, n = 2)
45
+ s = unindent(s)
46
+ ws = ' ' * n
47
+ s.gsub(%r/^/, ws)
48
+ end
49
+
50
+ def unindent(s)
51
+ indent = nil
52
+ s.each do |line|
53
+ next if line =~ %r/^\s*$/
54
+ indent = line[%r/^\s*/] and break
55
+ end
56
+ indent ? s.gsub(%r/^#{ indent }/, "") : s
57
+ end
58
+
59
+ samples = ''
60
+ prompt = '~ > '
61
+
62
+ Dir.chdir(File.dirname(__FILE__))
63
+
64
+ Dir['sample*/*'].sort.each do |sample|
65
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
66
+
67
+ cmd = "cat #{ sample }"
68
+ samples << indent(prompt + cmd, 2) << "\n\n"
69
+ samples << indent(`#{ cmd }`, 4) << "\n"
70
+
71
+ cmd = "ruby #{ sample }"
72
+ samples << indent(prompt + cmd, 2) << "\n\n"
73
+
74
+ cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -Ilib #{ sample })'"
75
+ #cmd = "ruby -Ilib #{ sample }"
76
+ samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
77
+ end
78
+
79
+ erb = ERB.new(unindent(template))
80
+ result = erb.result(binding)
81
+ #open('README', 'w'){|fd| fd.write result}
82
+ #puts unindent(result)
83
+ puts result
data/gemspec.rb CHANGED
@@ -1,35 +1,62 @@
1
- lib, version = File::basename(File::dirname(File::expand_path(__FILE__))).split %r/-/, 2
1
+ #! /usr/bin/env ruby
2
2
 
3
- require 'rubygems'
3
+ lib, version, *ignored = ARGV
4
4
 
5
- Gem::Specification::new do |spec|
6
- $VERBOSE = nil
5
+ unless lib
6
+ lib = File.basename(Dir.pwd)
7
+ end
7
8
 
8
- shiteless = lambda do |list|
9
- list.delete_if do |file|
10
- file =~ %r/\.svn/ or
11
- file =~ %r/\.tmp/
12
- end
13
- end
9
+ unless version
10
+ mod = lib.capitalize
11
+ require "./lib/#{ lib }"
12
+ version = eval(mod).send(:version)
13
+ end
14
+
15
+ abort('no lib') unless lib
16
+ abort('no version') unless version
14
17
 
15
- spec.name = lib
16
- spec.version = version
17
- spec.platform = Gem::Platform::RUBY
18
- spec.summary = lib
18
+ puts "### gemspec: #{ lib }-#{ version }"
19
19
 
20
- spec.files = shiteless[Dir::glob("**/**")]
21
- spec.executables = shiteless[Dir::glob("bin/*")].map{|exe| File::basename exe}
22
-
23
- spec.require_path = "lib"
20
+ $VERBOSE = nil
24
21
 
25
- spec.has_rdoc = File::exist? "doc"
26
- spec.test_suite_file = "test/#{ lib }.rb" if File::directory? "test"
27
- #spec.add_dependency 'lib', '>= version'
22
+ shiteless = lambda{|list| list.delete_if{|file| file =~ %r/\.(git|svn|tmp|sw.|bak)$/}}
28
23
 
29
- spec.extensions << "extconf.rb" if File::exists? "extconf.rb"
24
+ files = shiteless[Dir::glob("**/**")]
25
+ executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
26
+ has_rdoc = true #File.exist?('doc')
27
+ test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb")
30
28
 
31
- spec.rubyforge_project = 'codeforpeople'
32
- spec.author = "Ara T. Howard"
33
- spec.email = "ara.t.howard@gmail.com"
34
- spec.homepage = "http://codeforpeople.com/lib/ruby/#{ lib }/"
29
+ extensions = []
30
+ %w( Makefile configure extconf.rb rakefile Rakefile mkrf_conf ).each do |ext|
31
+ extensions << ext if File.exists?(ext)
35
32
  end
33
+
34
+ template = <<-__
35
+
36
+ Gem::Specification::new do |spec|
37
+ spec.name = #{ lib.inspect }
38
+ spec.version = #{ version.inspect }
39
+ spec.platform = Gem::Platform::RUBY
40
+ spec.summary = #{ lib.inspect }
41
+
42
+ spec.files = #{ files.inspect }
43
+ spec.executables = #{ executables.inspect }
44
+
45
+ spec.require_path = "lib"
46
+
47
+ spec.has_rdoc = #{ has_rdoc.inspect }
48
+ spec.test_files = #{ test_files.inspect }
49
+ #spec.add_dependency 'lib', '>= version'
50
+ #spec.add_dependency 'fattr'
51
+
52
+ spec.extensions.push(*#{ extensions.inspect })
53
+
54
+ spec.rubyforge_project = 'codeforpeople'
55
+ spec.author = "Ara T. Howard"
56
+ spec.email = "ara.t.howard@gmail.com"
57
+ spec.homepage = "http://github.com/ahoward/#{ lib }/tree/master"
58
+ end
59
+
60
+ __
61
+
62
+ puts template
data/install.rb CHANGED
File without changes
data/lib/threadify.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Threadify
2
- VERSION = '0.0.3'
2
+ VERSION = '1.0.0'
3
3
  def Threadify.version() Threadify::VERSION end
4
4
 
5
5
  require 'thread'
@@ -16,7 +16,7 @@ module Threadify
16
16
  end
17
17
 
18
18
  module Enumerable
19
- def threadify opts = {}, &block
19
+ def threadify(opts = {}, &block)
20
20
  # setup
21
21
  #
22
22
  opts = {:threads => opts} if Numeric === opts
@@ -29,13 +29,9 @@ module Enumerable
29
29
 
30
30
  # produce jobs
31
31
  #
32
- #producer = Thread.new do
33
- #this = Thread.current
34
- #this.abort_on_exception = Threadify.abort_on_exception
35
-
36
- each_with_index{|args, i| jobs[i % threads].push([args, i])}
37
- threads.times{|i| jobs[i].push(done)}
38
- #end
32
+ i = 0
33
+ each{|*args| jobs[i % threads].push([args, i]); i += 1}
34
+ threads.times{|i| jobs[i].push(done)}
39
35
 
40
36
  # setup consumer list
41
37
  #
@@ -107,17 +103,6 @@ module Enumerable
107
103
 
108
104
  # collect the results and return them
109
105
  #
110
- =begin
111
- jobs.push done
112
- ret = []
113
- while((job = jobs.pop) != done)
114
- elem, i, value = job
115
- ret[i] = value
116
- end
117
- ret
118
- end
119
- =end
120
-
121
106
  ret = []
122
107
  jobs.each do |results|
123
108
  results.each do |result|
@@ -132,13 +117,13 @@ module Enumerable
132
117
  end
133
118
 
134
119
  class Thread
135
- def Thread.ify enumerable, *args, &block
120
+ def Thread.ify(enumerable, *args, &block)
136
121
  enumerable.send :threadify, *args, &block
137
122
  end
138
123
  end
139
124
 
140
125
  class Object
141
- def threadify! *values
126
+ def threadify!(*values)
142
127
  throw :threadify, *values
143
128
  end
144
129
  end
data/threadify.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ ### gemspec: threadify-1.0.0
2
+
3
+ Gem::Specification::new do |spec|
4
+ spec.name = "threadify"
5
+ spec.version = "1.0.0"
6
+ spec.platform = Gem::Platform::RUBY
7
+ spec.summary = "threadify"
8
+
9
+ spec.files = ["gemspec.rb", "install.rb", "lib", "lib/threadify.rb", "README", "README.rb", "sample", "sample/a.rb", "sample/b.rb", "threadify.gemspec"]
10
+ spec.executables = []
11
+
12
+ spec.require_path = "lib"
13
+
14
+ spec.has_rdoc = true
15
+ spec.test_files = nil
16
+ #spec.add_dependency 'lib', '>= version'
17
+ #spec.add_dependency 'fattr'
18
+
19
+ spec.extensions.push(*[])
20
+
21
+ spec.rubyforge_project = 'codeforpeople'
22
+ spec.author = "Ara T. Howard"
23
+ spec.email = "ara.t.howard@gmail.com"
24
+ spec.homepage = "http://github.com/ahoward/threadify/tree/master"
25
+ end
26
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: threadify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ara T. Howard
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-07-11 00:00:00 -06:00
12
+ date: 2009-06-02 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -22,19 +22,18 @@ extensions: []
22
22
  extra_rdoc_files: []
23
23
 
24
24
  files:
25
- - a.rb
26
25
  - gemspec.rb
27
- - gen_readme.rb
28
26
  - install.rb
29
27
  - lib
30
28
  - lib/threadify.rb
31
- - lib/threadify.rb.bak
32
29
  - README
30
+ - README.rb
33
31
  - sample
34
32
  - sample/a.rb
35
33
  - sample/b.rb
36
- has_rdoc: false
37
- homepage: http://codeforpeople.com/lib/ruby/threadify/
34
+ - threadify.gemspec
35
+ has_rdoc: true
36
+ homepage: http://github.com/ahoward/threadify/tree/master
38
37
  post_install_message:
39
38
  rdoc_options: []
40
39
 
@@ -55,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
54
  requirements: []
56
55
 
57
56
  rubyforge_project: codeforpeople
58
- rubygems_version: 1.0.1
57
+ rubygems_version: 1.3.1
59
58
  signing_key:
60
59
  specification_version: 2
61
60
  summary: threadify
data/a.rb DELETED
@@ -1,10 +0,0 @@
1
- require 'threadify'
2
-
3
- a = Array.new(1024){|i| i}
4
-
5
- value =
6
- a.threadify do |i|
7
- threadify! i if i == 512
8
- end
9
-
10
- p value
data/gen_readme.rb DELETED
@@ -1,32 +0,0 @@
1
- require 'pathname'
2
-
3
- $VERBOSE=nil
4
-
5
- def indent s, n = 2
6
- ws = ' ' * n
7
- s.gsub %r/^/, ws
8
- end
9
-
10
- template = IO::read 'README.tmpl'
11
-
12
- samples = ''
13
- prompt = '~ > '
14
-
15
- Dir['sample*/*'].sort.each do |sample|
16
- samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
17
-
18
- cmd = "cat #{ sample }"
19
- samples << indent(prompt + cmd, 2) << "\n\n"
20
- samples << indent(`#{ cmd }`, 4) << "\n"
21
-
22
- cmd = "ruby #{ sample }"
23
- samples << indent(prompt + cmd, 2) << "\n\n"
24
-
25
- cmd = "ruby -Ilib #{ sample }"
26
- samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
27
- end
28
-
29
- #samples.gsub! %r/^/, ' '
30
-
31
- readme = template.gsub %r/^\s*@samples\s*$/, samples
32
- print readme
data/lib/threadify.rb.bak DELETED
@@ -1,154 +0,0 @@
1
- module Threadify
2
- VERSION = '0.0.3'
3
- def Threadify.version() Threadify::VERSION end
4
-
5
- require 'thread'
6
-
7
- @threads = 8
8
- @abort_on_exception = true
9
-
10
- class << self
11
- attr_accessor :threads
12
- attr_accessor :abort_on_exception
13
- end
14
-
15
- class Error < ::StandardError; end
16
- end
17
-
18
- module Enumerable
19
- def threadify opts = {}, &block
20
- # setup
21
- #
22
- opts = {:threads => opts} if Numeric === opts
23
- threads = Integer(opts[:threads] || opts['threads'] || Threadify.threads)
24
- done = Object.new.freeze
25
- nothing = done
26
- jobs = Queue.new
27
- top = Thread.current
28
-
29
- # produce jobs
30
- #
31
- producer = Thread.new do
32
- each_with_index{|args, i| jobs.push [args, i]}
33
- threads.times{ jobs.push done}
34
- end
35
-
36
- # setup consumer list
37
- #
38
- consumers = Array.new threads
39
-
40
- # setup support for short-circuit bailout via 'throw :threadify'
41
- #
42
- thrownv = Hash.new
43
- thrownq = Queue.new
44
-
45
- caught = false
46
-
47
- catcher = Thread.new do
48
- loop do
49
- thrown = thrownq.pop
50
- break if thrown == done
51
- i, thrown = thrown
52
- thrownv[i] = thrown
53
- caught = true
54
- end
55
- end
56
-
57
- # fire off the consumers
58
- #
59
- threads.times do |i|
60
- consumers[i] =
61
- Thread.new do
62
- this = Thread.current
63
- this.abort_on_exception = Threadify.abort_on_exception
64
-
65
- job = nil
66
-
67
- thrown =
68
- catch(:threadify) do
69
- loop{
70
- break if caught
71
- job = jobs.pop
72
- break if job == done
73
- args = job.first
74
- jobs << (job << block.call(*args))
75
- }
76
- nothing
77
- end
78
-
79
-
80
- unless nothing == thrown
81
- args, i = job
82
- thrownq.push [i, thrown]
83
- end
84
- end
85
- end
86
-
87
- # wait for consumers to finish
88
- #
89
- consumers.map{|t| t.join}
90
-
91
- # nuke the catcher
92
- #
93
- thrownq.push done
94
- catcher.join
95
-
96
- # iff something(s) was thrown return the one which would have been thrown
97
- # earliest in non-parallel execution
98
- #
99
- unless thrownv.empty?
100
- key = thrownv.keys.sort.first
101
- return thrownv[key]
102
- end
103
-
104
- # collect the results and return them
105
- #
106
- jobs.push done
107
- ret = []
108
- while((job = jobs.pop) != done)
109
- elem, i, value = job
110
- ret[i] = value
111
- end
112
- ret
113
- end
114
-
115
- end
116
-
117
- class Thread
118
- def Thread.ify enumerable, *args, &block
119
- enumerable.send :threadify, *args, &block
120
- end
121
- end
122
-
123
- class Object
124
- def threadify! *values
125
- throw :threadify, *values
126
- end
127
- end
128
-
129
-
130
- if __FILE__ == $0
131
- require 'open-uri'
132
- require 'yaml'
133
-
134
- uris = %w( http://google.com http://yahoo.com http://rubyforge.org/ http://ruby-lang.org)
135
-
136
- Thread.ify uris, :threads => 3 do |uri|
137
- body = open(uri){|pipe| pipe.read}
138
- y uri => body.size
139
- end
140
- end
141
-
142
-
143
- __END__
144
-
145
- sample output
146
-
147
- ---
148
- http://yahoo.com: 9562
149
- ---
150
- http://google.com: 6290
151
- ---
152
- http://rubyforge.org/: 22352
153
- ---
154
- http://ruby-lang.org: 9984