iprocess 4.0.0 → 5.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.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: