dakrone-forkify 0.0.1 → 0.0.2
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/History.txt +7 -0
- data/Manifest.txt +1 -0
- data/README.txt +1 -1
- data/Rakefile +3 -2
- data/examples/c.rb +15 -0
- data/lib/forkify.rb +43 -16
- data/test/test_forkify.rb +13 -0
- metadata +3 -2
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
data/README.txt
CHANGED
data/Rakefile
CHANGED
@@ -4,12 +4,13 @@ require 'rubygems'
|
|
4
4
|
require 'hoe'
|
5
5
|
require './lib/forkify.rb'
|
6
6
|
|
7
|
-
FORKIFY_VERSION = "0.0.
|
7
|
+
FORKIFY_VERSION = "0.0.2"
|
8
8
|
|
9
9
|
Hoe.spec('forkify') do
|
10
10
|
version = FORKIFY_VERSION
|
11
11
|
developer('Lee Hinman', 'lee@writequit.org')
|
12
|
-
|
12
|
+
rubyforge_name = 'hinmanm'
|
13
13
|
end
|
14
14
|
|
15
|
+
|
15
16
|
# vim: syntax=Ruby
|
data/examples/c.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# vim: set ts=2 sw=2 filetype=Ruby
|
3
|
+
#
|
4
|
+
# This example shows a problem with the current implementation of forkify:
|
5
|
+
# if a fork finishes work, it will still wait for the other forks to finish
|
6
|
+
# in the process pool before forking new processes for work.
|
7
|
+
#
|
8
|
+
# I hope to remedy this as soon as I figure out a good solution for it.
|
9
|
+
|
10
|
+
require 'forkify'
|
11
|
+
|
12
|
+
[1, 1, 1, 1, 5, 1].forkify(5) { |n| puts n; sleep(n); n }
|
13
|
+
|
14
|
+
# 0.04s user 0.06s system 1% cpu 6.031 total
|
15
|
+
# (would be possible to run in a little over 5)
|
data/lib/forkify.rb
CHANGED
@@ -1,9 +1,27 @@
|
|
1
|
-
|
1
|
+
FORKIFY_DEBUG = false
|
2
|
+
require 'pp' if FORKIFY_DEBUG
|
2
3
|
|
3
4
|
module Enumerable
|
5
|
+
|
6
|
+
#
|
7
|
+
# Forkify will process _block_'s actions using processes. If no number of processes is
|
8
|
+
# given, the default of 5 will be used. If there are less than _procs_ number of items
|
9
|
+
# in the +Enumerable+ type, less processes will be spawned.
|
10
|
+
#
|
11
|
+
# It should be noted that forkify will *always* return an +Array+ at this time, so be
|
12
|
+
# careful with +Hash+ objects.
|
13
|
+
#
|
14
|
+
# = Examples
|
15
|
+
#
|
16
|
+
# [1, 2, 3].forkify { |n| n*2 } => [2, 4, 6]
|
17
|
+
#
|
18
|
+
# {:a => 1, :b => 2, :c => 3}.forkify { |k, v| [v, k] } => [[1, :a], [2, :b], [3, :c]]
|
19
|
+
#
|
20
|
+
# 10.times.forkify(10) { sleep(1) } => [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] (runs for less than 2 seconds)
|
21
|
+
#
|
4
22
|
def forkify procs = 5, &block
|
5
|
-
|
6
|
-
if
|
23
|
+
puts "Forkify Class: #{self.class}" if FORKIFY_DEBUG
|
24
|
+
if self === Array
|
7
25
|
items = self
|
8
26
|
else
|
9
27
|
begin
|
@@ -27,9 +45,9 @@ module Enumerable
|
|
27
45
|
rpipes = []
|
28
46
|
|
29
47
|
num_procs.times do |i|
|
30
|
-
|
48
|
+
puts "Fork # #{i}" if FORKIFY_DEBUG
|
31
49
|
r, w = IO.pipe
|
32
|
-
|
50
|
+
pp "r, w: #{r} #{w}" if FORKIFY_DEBUG
|
33
51
|
wpipes << w
|
34
52
|
rpipes << r
|
35
53
|
pid = fork
|
@@ -52,19 +70,27 @@ module Enumerable
|
|
52
70
|
|
53
71
|
offset += num_procs
|
54
72
|
|
55
|
-
|
73
|
+
pp "Waiting for pids: #{pids.inspect}" if FORKIFY_DEBUG
|
56
74
|
pids.each { |p| Process.waitpid(p) }
|
57
75
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
#
|
62
|
-
|
63
|
-
#
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
76
|
+
# 1 select version
|
77
|
+
#datawaiting_pipes = Kernel.select(rpipes, wpipes, nil, 2)
|
78
|
+
#readwaiting_pipes = datawaiting_pipes[0]
|
79
|
+
#writewaiting_pipes = datawaiting_pipes[1]
|
80
|
+
|
81
|
+
# Switch to 2 selects instead of 1
|
82
|
+
#readwaiting_pipes = Kernel.select(rpipes, nil, nil, 2)[0]
|
83
|
+
#writewaiting_pipes = Kernel.select(nil, wpipes, nil, 2)[1]
|
84
|
+
|
85
|
+
# Finally settled on going through the pipes instead of select for Linux bug
|
86
|
+
unless rpipes.size != wpipes.size
|
87
|
+
rpipes.size.times do |i|
|
88
|
+
r = rpipes[i]
|
89
|
+
w = wpipes[i]
|
90
|
+
|
91
|
+
pp "read: #{readwaiting_pipes}" if FORKIFY_DEBUG
|
92
|
+
pp "write: #{writewaiting_pipes}" if FORKIFY_DEBUG
|
93
|
+
|
68
94
|
w.close
|
69
95
|
data = ''
|
70
96
|
while ( buf = r.read(8192) )
|
@@ -72,6 +98,7 @@ module Enumerable
|
|
72
98
|
end
|
73
99
|
result = Marshal.load( data )
|
74
100
|
r.close
|
101
|
+
pp "Pushing result: #{result}" if FORKIFY_DEBUG
|
75
102
|
results << result
|
76
103
|
end
|
77
104
|
end
|
data/test/test_forkify.rb
CHANGED
@@ -15,4 +15,17 @@ Testy.testing 'forkify' do
|
|
15
15
|
r = [1, 2, 3].forkify { |n| n * 2 }
|
16
16
|
t.check :array_results, :expect => [2, 4, 6], :actual => r
|
17
17
|
end
|
18
|
+
|
19
|
+
test 'hash results' do |t|
|
20
|
+
r = {:a => 1, :b => 2, :c => 3}.forkify { |k, v| [k, v*2] }
|
21
|
+
t.check :hash_contains_a, :expect => true, :actual => r.include?([:a, 2])
|
22
|
+
t.check :hash_contains_b, :expect => true, :actual => r.include?([:b, 4])
|
23
|
+
t.check :hash_contains_c, :expect => true, :actual => r.include?([:c, 6])
|
24
|
+
t.check :hash_length, :expect => 3, :actual => r.size
|
25
|
+
end
|
26
|
+
|
27
|
+
test 'array of nils' do |t|
|
28
|
+
r = [nil, nil].forkify { |n| n }
|
29
|
+
t.check :nil_array, :expect => [nil, nil], :actual => r
|
30
|
+
end
|
18
31
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dakrone-forkify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lee Hinman
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-29 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,6 +42,7 @@ files:
|
|
42
42
|
- test/test_forkify.rb
|
43
43
|
- examples/a.rb
|
44
44
|
- examples/b.rb
|
45
|
+
- examples/c.rb
|
45
46
|
has_rdoc: false
|
46
47
|
homepage: http://github.com/dakrone/forkify
|
47
48
|
post_install_message:
|