threadify 0.0.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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