iprocess 4.0.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -12,11 +12,11 @@ __OVERVIEW__
12
12
  __DESCRIPTION__
13
13
 
14
14
  Provides a number of abstractions on top of spawning subprocesses and
15
- interprocess communication. The API is simple, easy to use & supports
16
- both synchronous and asynchronous(non-blocking) dispatch of subprocesses.
17
- It also supports implicit interprocess communication that can be easily
18
- configured to use the serializer of your choice(default is the
19
- [Marshal](http://rdoc.info/stdlib/core/Marshal) module) if needs be.
15
+ interprocess communication. The API is simple and supports both synchronous and
16
+ asynchronous(non-blocking) dispatch of subprocesses. It also supports implicit
17
+ interprocess communication that can be easily configured to use the serializer
18
+ of your choice(default is the [Marshal](http://rdoc.info/stdlib/core/Marshal)
19
+ module) if needs be.
20
20
 
21
21
  __EXAMPLES__
22
22
 
@@ -52,17 +52,20 @@ __3.__
52
52
  A demo of how you would spawn two subprocesses asynchronously:
53
53
 
54
54
  class Inbox
55
+ attr_reader :msgs
56
+
55
57
  def initialize
56
- @messages = []
58
+ @msgs = []
57
59
  end
58
60
 
59
61
  def recv(msg)
60
- @messages << msg
62
+ @msgs << msg
61
63
  end
62
64
  end
63
65
  inbox = Inbox.new
64
- jobs = IProcess.spawn!(2) { Process.pid }
65
- jobs.each { |job| job.report_to(inbox) }
66
+ IProcess.spawn!(2, Inbox.new) { Process.pid }
67
+ sleep 0.1
68
+ p inbox.msgs
66
69
 
67
70
  __SERIALIZERS__
68
71
 
@@ -106,13 +109,6 @@ __INSTALL__
106
109
 
107
110
  $ gem install iprocess
108
111
 
109
- __SEE ALSO__
110
-
111
- - [XPool](https://github.com/robgleeson/xpool)
112
- XPool is a UNIX process pool that was born inside IProcess but later extracted
113
- into its own project. It might be interesting to you if you're interested in
114
- concurrency and/or interprocess communication.
115
-
116
112
  __LICENSE__
117
113
 
118
114
  MIT. See LICENSE.txt.
data/iprocess.gemspec CHANGED
@@ -7,7 +7,8 @@ Gem::Specification.new do |s|
7
7
  s.authors = ["Rob Gleeson"]
8
8
  s.email = 'rob@flowof.info'
9
9
  s.homepage = 'https://github.com/robgleeson/iprocess'
10
- s.summary = 'IProcess makes InterProcess Communication(IPC) easy.'
10
+ s.summary = 'A number of abstractions on top of spawning subprocesses ' \
11
+ 'and interprocess communication.'
11
12
  s.description = s.summary
12
13
 
13
14
  s.files = `git ls-files`.each_line.map(&:chomp)
data/lib/iprocess.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  class IProcess
2
2
  require 'ichannel'
3
3
  require_relative 'iprocess/version'
4
+
4
5
  #
5
6
  # @return [#load,#dump]
6
7
  # Returns the serializer used by IProcess.
7
8
  #
8
- def self.serializer
9
+ def self.serializer
9
10
  @serializer || Marshal
10
11
  end
11
12
 
@@ -19,9 +20,7 @@ class IProcess
19
20
  end
20
21
 
21
22
  #
22
- # @overload spawn(number_of = 1, worker)
23
- #
24
- # Spawn one or more subprocesses.
23
+ # Spawn one or more subprocesse(s).
25
24
  #
26
25
  # @param [Integer] number_of
27
26
  # The number of subprocesses to spawn.
@@ -30,25 +29,35 @@ class IProcess
30
29
  # The unit of work to execute in a subprocess.
31
30
  #
32
31
  # @return [Array<Object>]
33
- # The return value(s) of the unit(s) of work.
34
- #
35
- def self.spawn(*args, &worker)
36
- fork(*args, &worker).map(&:result)
32
+ # The return value of the unit of work.
33
+ #
34
+ # @example
35
+ # IProcess.spawn 2 do
36
+ # {ok: true}
37
+ # end
38
+ #
39
+ def self.spawn(number_of, obj = nil, &worker)
40
+ fork(number_of, obj, &worker).map(&:result)
37
41
  end
38
42
 
39
43
  #
40
- # @overload
41
- #
42
- # Spawn one or more subprocesses asynchronously.
44
+ # Spawn one or more subprocesse(s) asynchronously.
43
45
  #
44
- # @param
45
- # (see IProcess.spawn)
46
+ # @param [#recv] inbox
47
+ # An object who can receive messages through the {#recv} method.
46
48
  #
47
- # @return [Array<IProcess>]
48
- # An array of IProcess objects. See {#report_to}.
49
+ # @param
50
+ # (see IProcess.spawn)
49
51
  #
50
- def self.spawn!(*args, &worker)
51
- fork *args, &worker
52
+ # @return [Array<IProcess>]
53
+ #
54
+ def self.spawn!(number_of, inbox, obj = nil, &worker)
55
+ forks = fork number_of, obj, &worker
56
+ forks.each do |subprocess|
57
+ Thread.new do
58
+ inbox.recv subprocess.result
59
+ end
60
+ end
52
61
  end
53
62
 
54
63
  def self.fork(number_of = 1, obj = nil, &worker)
@@ -61,10 +70,10 @@ class IProcess
61
70
 
62
71
  #
63
72
  # @param [#call] worker
64
- # Any object that implements #call.
73
+ # The unit of work to execute in a subprocess.
65
74
  #
66
75
  # @raise [ArgumentError]
67
- # If 'worker' does not respond to #call.
76
+ # If a worker is not given.
68
77
  #
69
78
  # @return [IProcess]
70
79
  # Returns self.
@@ -72,7 +81,7 @@ class IProcess
72
81
  def initialize(worker)
73
82
  @worker = worker
74
83
  @channel = nil
75
- @pid = nil
84
+ @pid = nil
76
85
  unless @worker.respond_to?(:call)
77
86
  raise ArgumentError,
78
87
  "Expected worker to implement #{@worker.class}#call"
@@ -80,34 +89,14 @@ class IProcess
80
89
  end
81
90
 
82
91
  #
83
- # @param [#recv] obj
84
- # An object that will receive messages.
85
- #
86
- # @return [void]
87
- #
88
- def report_to(obj)
89
- thr = Thread.new do
90
- Process.wait @pid
91
- obj.recv @channel.recv
92
- end
93
- pid = Process.pid
94
- at_exit do
95
- is_parent = pid == Process.pid
96
- if is_parent && thr.alive?
97
- thr.join
98
- end
99
- end
100
- end
101
-
102
- #
103
- # Executes a subprocess.
92
+ # Executes a unit of work in a subprocess.
104
93
  #
105
94
  # @return [Fixnum]
106
95
  # The process ID of the spawned subprocess.
107
96
  #
108
97
  def execute
109
98
  @channel = IChannel.new IProcess.serializer
110
- @pid = fork { @channel.put(@worker.call) }
99
+ @pid = fork { @channel.write(@worker.call) }
111
100
  end
112
101
 
113
102
  #
@@ -116,6 +105,6 @@ class IProcess
116
105
  #
117
106
  def result
118
107
  Process.wait(@pid)
119
- @channel.get
108
+ @channel.recv
120
109
  end
121
110
  end
@@ -1,3 +1,3 @@
1
1
  class IProcess
2
- VERSION = '4.0.0'
2
+ VERSION = '5.0.0'
3
3
  end
data/test/setup.rb CHANGED
@@ -1,3 +1,5 @@
1
1
  require 'iprocess'
2
2
  require 'test/unit'
3
- require 'minitest/mock'
3
+ Dir["test/*.rb", "test/support/*.rb"].each do |test|
4
+ require "./#{test}"
5
+ end
@@ -0,0 +1,13 @@
1
+ class Inbox
2
+ def initialize
3
+ @msgs = []
4
+ end
5
+
6
+ def messages
7
+ @msgs
8
+ end
9
+
10
+ def recv(msg)
11
+ @msgs << msg
12
+ end
13
+ end
@@ -1,25 +1,24 @@
1
- require_relative "setup"
1
+ require_relative 'setup'
2
2
  class IProcessTest < Test::Unit::TestCase
3
- def test_serializer_default_value
4
- assert_equal Marshal, IProcess.serializer
3
+ def test_spawn
4
+ results = IProcess.spawn(2) { :ok }
5
+ assert_equal [:ok, :ok], results
5
6
  end
6
7
 
7
- def test_block_worker
8
- messages = IProcess.spawn(2) { :hello }
9
- assert_equal [:hello, :hello], messages
10
- end
11
-
12
- def test_duck_typed_worker
13
- messages = IProcess.spawn 2, worker.new
14
- assert_equal [:hello, :hello], messages
15
- end
16
-
17
- private
18
- def worker
19
- Class.new do
8
+ def test_spawn_with_non_proc_worker
9
+ klass = Class.new do
20
10
  def call
21
- :hello
11
+ :ok
22
12
  end
23
13
  end
14
+ results = IProcess.spawn 2, klass.new
15
+ assert_equal [:ok, :ok], results
16
+ end
17
+
18
+ def test_async_spawn!
19
+ inbox = Inbox.new
20
+ IProcess.spawn!(2, inbox) { {ok: true} }
21
+ sleep 0.1
22
+ assert_equal [{ok: true}, {ok: true}], inbox.messages
24
23
  end
25
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iprocess
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 5.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-15 00:00:00.000000000 Z
12
+ date: 2013-01-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ichannel
@@ -91,7 +91,8 @@ dependencies:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
- description: IProcess makes InterProcess Communication(IPC) easy.
94
+ description: A number of abstractions on top of spawning subprocesses and interprocess
95
+ communication.
95
96
  email: rob@flowof.info
96
97
  executables: []
97
98
  extensions: []
@@ -110,6 +111,7 @@ files:
110
111
  - lib/iprocess.rb
111
112
  - lib/iprocess/version.rb
112
113
  - test/setup.rb
114
+ - test/support/inbox_class.rb
113
115
  - test/test_IProcess_class.rb
114
116
  homepage: https://github.com/robgleeson/iprocess
115
117
  licenses: []
@@ -134,8 +136,10 @@ rubyforge_project: ! '[none]'
134
136
  rubygems_version: 1.8.23
135
137
  signing_key:
136
138
  specification_version: 3
137
- summary: IProcess makes InterProcess Communication(IPC) easy.
139
+ summary: A number of abstractions on top of spawning subprocesses and interprocess
140
+ communication.
138
141
  test_files:
139
142
  - test/setup.rb
143
+ - test/support/inbox_class.rb
140
144
  - test/test_IProcess_class.rb
141
145
  has_rdoc: