process-group 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a8d207f2d37df9b65b6e179ac9109dd9e3a5a443
4
- data.tar.gz: 4422d1d9fc5171dc8dc5236b4b9745fbe81dda5b
3
+ metadata.gz: 026f8b1f40e77c491180b9faff360d884a6717fa
4
+ data.tar.gz: c4ecc9c7c932b7c662f420f3c82ece3ea0a6d7b1
5
5
  SHA512:
6
- metadata.gz: f2c49a5f6980e9bb4b44c90f5577e5a664611bef83e22da9f3e5bfbc1525870a76a4ff11cffa36340b30f77e594e75e8de3b55f04132537d10b92bce2a85452c
7
- data.tar.gz: 348213c1cf609dace2d8228a9111b53232cc4bf36cde8c548d62e93bc5ee4e3bb1a5fac5fe5083e2029298201e3b6636e91f8d17319946510bb74e00800aa9d5
6
+ metadata.gz: e364e21669e91dec753aff10d6100584c0d80057a52a4db539fcc3fb57df1b2a58b1d69220f66d9c9e8ce137383b5b7f9b62d780e51b292d295e0f5e38c283c0
7
+ data.tar.gz: c723127bf2fc53e8d9752f016e858ea1417f053548d687f4732866bfc29275fc80b0680f5609aee396c99fc0c2c8ad996d6396afa3d6b9a55ca6d7cf96731d5d
data/lib/process/group.rb CHANGED
@@ -35,7 +35,36 @@ module Process
35
35
  attr :options
36
36
 
37
37
  def run(options = {})
38
- Process.spawn(*@arguments, @options.merge(options))
38
+ @pid = Process.spawn(*@arguments, @options.merge(options))
39
+
40
+ return @pid
41
+ end
42
+
43
+ def resume(*arguments)
44
+ @fiber.resume(*arguments)
45
+ end
46
+ end
47
+
48
+ class Fork
49
+ def initialize(block, options, fiber = Fiber.current)
50
+ @options = options
51
+ @block = block
52
+
53
+ @fiber = fiber
54
+ end
55
+
56
+ def run(options = {})
57
+ @pid = Process.fork(&@block)
58
+
59
+ if options[:pgroup] == true
60
+ # Establishes the child process as a process group leader:
61
+ Process.setpgid(@pid, 0)
62
+ else
63
+ # Set this process as part of the existing process group:
64
+ Process.setpgid(@pid, options[:pgroup])
65
+ end
66
+
67
+ return @pid
39
68
  end
40
69
 
41
70
  def resume(*arguments)
@@ -45,7 +74,7 @@ module Process
45
74
 
46
75
  # Create a new process group. Can specify `options[:limit]` which limits the maximum number of concurrent processes.
47
76
  def initialize(options = {})
48
- @commands = []
77
+ @queue = []
49
78
  @limit = options[:limit]
50
79
 
51
80
  @running = {}
@@ -80,11 +109,11 @@ module Process
80
109
  # Could be nice to use ** splat, but excludes ruby < 2.0.
81
110
  options = Hash === arguments.last ? arguments.pop : {}
82
111
 
83
- @commands << Command.new(arguments, options)
84
-
85
- schedule!
86
-
87
- Fiber.yield
112
+ append! Command.new(arguments, options)
113
+ end
114
+
115
+ def fork(options = {}, &block)
116
+ append! Fork.new(block, options)
88
117
  end
89
118
 
90
119
  # Whether not not calling run would be scheduled immediately.
@@ -107,14 +136,17 @@ module Process
107
136
  # Wait for processes in this group:
108
137
  pid, status = Process.wait2(-@pgid)
109
138
 
110
- command = @running.delete(pid)
139
+ process = @running.delete(pid)
111
140
 
112
- raise RuntimeError.new("Process #{pid} is not part of group!") unless command
141
+ raise RuntimeError.new("Process id=#{pid} is not part of group!") unless process
113
142
 
114
143
  schedule!
115
144
 
116
- command.resume(status)
145
+ process.resume(status)
117
146
  end
147
+
148
+ # No processes, process group is no longer valid:
149
+ @pgid = nil
118
150
  end
119
151
 
120
152
  # Send a signal to all processes.
@@ -126,19 +158,29 @@ module Process
126
158
 
127
159
  private
128
160
 
129
- # Run any commands while space is available in the group.
161
+ def append!(process)
162
+ @queue << process
163
+
164
+ schedule!
165
+
166
+ Fiber.yield
167
+ end
168
+
169
+ # Run any processes while space is available in the group.
130
170
  def schedule!
131
- while available? and @commands.size > 0
132
- command = @commands.shift
171
+ while available? and @queue.size > 0
172
+ process = @queue.shift
133
173
 
134
174
  if @running.size == 0
135
- pid = command.run(:pgroup => true)
136
- @pgid = Process.getpgid(pid)
175
+ pid = process.run(:pgroup => true)
176
+
177
+ # The process group id is the pid of the first process:
178
+ @pgid = pid
137
179
  else
138
- pid = command.run(:pgroup => @pgid)
180
+ pid = process.run(:pgroup => @pgid)
139
181
  end
140
182
 
141
- @running[pid] = command
183
+ @running[pid] = process
142
184
  end
143
185
  end
144
186
  end
@@ -1,5 +1,5 @@
1
1
  module Process
2
2
  class Group
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
data/test/test_fork.rb ADDED
@@ -0,0 +1,47 @@
1
+ # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'test/unit'
22
+
23
+ require 'process/group'
24
+
25
+ class TestFork < Test::Unit::TestCase
26
+ def test_fork_io
27
+ group = Process::Group.new
28
+
29
+ input, output = IO.pipe
30
+
31
+ Fiber.new do
32
+ result = group.fork do
33
+ output.puts "Hello World"
34
+
35
+ exit(1)
36
+ end
37
+
38
+ assert_equal 1, result.exitstatus
39
+ end.resume
40
+
41
+ output.close
42
+
43
+ group.wait
44
+
45
+ assert_equal "Hello World\n", input.read
46
+ end
47
+ end
@@ -22,7 +22,7 @@ require 'test/unit'
22
22
 
23
23
  require 'process/group'
24
24
 
25
- class TestGroup < Test::Unit::TestCase
25
+ class TestSpawn < Test::Unit::TestCase
26
26
  def test_fibers
27
27
  group = Process::Group.new
28
28
 
@@ -35,6 +35,7 @@ class TestGroup < Test::Unit::TestCase
35
35
 
36
36
  Fiber.new do
37
37
  result = group.spawn("sleep 2")
38
+
38
39
  assert_equal 0, result
39
40
  end.resume
40
41
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: process-group
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-11 00:00:00.000000000 Z
11
+ date: 2014-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,7 +56,8 @@ files:
56
56
  - lib/process/group.rb
57
57
  - lib/process/group/version.rb
58
58
  - process-group.gemspec
59
- - test/test_group.rb
59
+ - test/test_fork.rb
60
+ - test/test_spawn.rb
60
61
  homepage: ''
61
62
  licenses:
62
63
  - MIT
@@ -82,4 +83,5 @@ signing_key:
82
83
  specification_version: 4
83
84
  summary: Run processes concurrently in separate fibers with predictable behaviour.
84
85
  test_files:
85
- - test/test_group.rb
86
+ - test/test_fork.rb
87
+ - test/test_spawn.rb