iprocess 3.1.2 → 3.2.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/.pryrc +1 -0
- data/.yardopts +1 -0
- data/README.md +8 -7
- data/lib/iprocess.rb +54 -56
- data/lib/iprocess/channel.rb +21 -17
- data/lib/iprocess/version.rb +1 -1
- data/test/setup.rb +1 -3
- metadata +3 -2
data/.pryrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "./lib/iprocess"
|
data/.yardopts
CHANGED
data/README.md
CHANGED
@@ -5,15 +5,16 @@ __OVERVIEW__
|
|
5
5
|
|:----------------|:--------------------------------------------------
|
6
6
|
| Homepage | https://github.com/robgleeson/IProcess
|
7
7
|
| Documentation | http://rubydoc.info/gems/iprocess/frames
|
8
|
+
| CI | [](https://travis-ci.org/robgleeson/iprocess)
|
8
9
|
| Author | Rob Gleeson
|
9
10
|
|
10
11
|
|
11
12
|
__DESCRIPTION__
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
Provides a number of abstractions on top of spawning subprocesses and
|
15
|
+
interprocess communication. It has a simple and easy to use API that
|
16
|
+
supports synchronous and asynchronous method calls plus one or two other
|
17
|
+
useful features shown in the examples below.
|
17
18
|
|
18
19
|
__EXAMPLES__
|
19
20
|
|
@@ -59,7 +60,7 @@ A demo of how you would spawn two subprocesses asynchronously:
|
|
59
60
|
end
|
60
61
|
inbox = Inbox.new
|
61
62
|
jobs = IProcess.spawn!(2) { Process.pid }
|
62
|
-
jobs.
|
63
|
+
jobs.each { |job| job.report_to(inbox) }
|
63
64
|
|
64
65
|
__SERIALIZERS__
|
65
66
|
|
@@ -69,8 +70,8 @@ the `IProcess.serializer=` method:
|
|
69
70
|
|
70
71
|
IProcess.serializer = JSON
|
71
72
|
|
72
|
-
I know JSON & Marshal(the default) are supported out of
|
73
|
-
the box because
|
73
|
+
I know JSON, YAML & Marshal(the default) are supported out of
|
74
|
+
the box because all of them implement both of those methods.
|
74
75
|
MessagePack does not however but you could easily write
|
75
76
|
a wrapper:
|
76
77
|
|
data/lib/iprocess.rb
CHANGED
@@ -1,66 +1,63 @@
|
|
1
1
|
class IProcess
|
2
2
|
require_relative 'iprocess/version'
|
3
3
|
require_relative 'iprocess/channel'
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@serializer || Marshal
|
12
|
-
end
|
4
|
+
#
|
5
|
+
# @return [#load,#dump]
|
6
|
+
# Returns the serializer used by IProcess.
|
7
|
+
#
|
8
|
+
def self.serializer
|
9
|
+
@serializer || Marshal
|
10
|
+
end
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
#
|
13
|
+
# @param [#load,#dump] obj
|
14
|
+
# Any object that implements #load, & #dump.
|
15
|
+
# Examples could be JSON & Marshal.
|
16
|
+
#
|
17
|
+
def self.serializer=(obj)
|
18
|
+
@serializer = obj
|
19
|
+
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
21
|
+
#
|
22
|
+
# @overload spawn(number_of = 1, worker)
|
23
|
+
#
|
24
|
+
# Spawn one or more subprocesses.
|
25
|
+
#
|
26
|
+
# @param [Integer] number_of
|
27
|
+
# The number of subprocesses to spawn.
|
28
|
+
#
|
29
|
+
# @param [#call] worker
|
30
|
+
# The unit of work to execute in a subprocess.
|
31
|
+
#
|
32
|
+
# @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)
|
37
|
+
end
|
40
38
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
39
|
+
#
|
40
|
+
# @overload
|
41
|
+
#
|
42
|
+
# Spawn one or more subprocesses asynchronously.
|
43
|
+
#
|
44
|
+
# @param
|
45
|
+
# (see IProcess.spawn)
|
46
|
+
#
|
47
|
+
# @return [Array<IProcess>]
|
48
|
+
# An array of IProcess objects. See {#report_to}.
|
49
|
+
#
|
50
|
+
def self.spawn!(*args, &worker)
|
51
|
+
fork *args, &worker
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.fork(number_of = 1, obj = nil, &worker)
|
55
|
+
worker = obj || worker
|
56
|
+
Array.new(number_of) do
|
57
|
+
IProcess.new(worker).tap { |job| job.execute }
|
61
58
|
end
|
62
|
-
private :fork
|
63
59
|
end
|
60
|
+
private_class_method :fork
|
64
61
|
|
65
62
|
#
|
66
63
|
# @param [#call] worker
|
@@ -95,7 +92,8 @@ class IProcess
|
|
95
92
|
end
|
96
93
|
pid = Process.pid
|
97
94
|
at_exit do
|
98
|
-
|
95
|
+
is_parent = pid == Process.pid
|
96
|
+
if is_parent && thr.alive?
|
99
97
|
thr.join
|
100
98
|
end
|
101
99
|
end
|
data/lib/iprocess/channel.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
+
require 'socket'
|
1
2
|
class IProcess::Channel
|
2
|
-
|
3
3
|
#
|
4
4
|
# @param [#dump,#load}] serializer
|
5
5
|
# Any object that implements dump, & load.
|
@@ -9,7 +9,7 @@ class IProcess::Channel
|
|
9
9
|
# Yields self.
|
10
10
|
#
|
11
11
|
def initialize(serializer = IProcess.serializer)
|
12
|
-
@reader, @writer =
|
12
|
+
@reader, @writer = UNIXSocket.pair :DGRAM
|
13
13
|
@serializer = serializer
|
14
14
|
if block_given?
|
15
15
|
yield self
|
@@ -17,7 +17,14 @@ class IProcess::Channel
|
|
17
17
|
end
|
18
18
|
|
19
19
|
#
|
20
|
-
#
|
20
|
+
# Close the channel.
|
21
|
+
#
|
22
|
+
# @return [void]
|
23
|
+
#
|
24
|
+
def close
|
25
|
+
[@reader.close,@writer.close]
|
26
|
+
end
|
27
|
+
|
21
28
|
#
|
22
29
|
# @return [Boolean]
|
23
30
|
# Returns true if the channel is closed.
|
@@ -26,8 +33,6 @@ class IProcess::Channel
|
|
26
33
|
@reader.closed? && @writer.closed?
|
27
34
|
end
|
28
35
|
|
29
|
-
#
|
30
|
-
# Is the channel open?
|
31
36
|
#
|
32
37
|
# @return [Boolean]
|
33
38
|
# Returns true if the channel is open.
|
@@ -37,18 +42,18 @@ class IProcess::Channel
|
|
37
42
|
end
|
38
43
|
|
39
44
|
#
|
40
|
-
#
|
45
|
+
# Add an object to the channel.
|
41
46
|
#
|
42
47
|
# @param [Object] object
|
43
|
-
#
|
48
|
+
# An object to add to the channel.
|
44
49
|
#
|
45
50
|
def write object
|
46
|
-
|
47
|
-
|
48
|
-
@writer.
|
49
|
-
@writer.close
|
51
|
+
_, writable, _ = IO.select [], [@writer], [], 0.1
|
52
|
+
if writable
|
53
|
+
@writer.send @serializer.dump(object), 0
|
50
54
|
end
|
51
55
|
end
|
56
|
+
alias_method :put, :write
|
52
57
|
|
53
58
|
#
|
54
59
|
# Receive a object from the channel.
|
@@ -57,12 +62,11 @@ class IProcess::Channel
|
|
57
62
|
# The object added to the channel.
|
58
63
|
#
|
59
64
|
def recv
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
@
|
64
|
-
obj
|
65
|
+
readable, _ = IO.select [@reader], [], [], 0.1
|
66
|
+
if readable
|
67
|
+
msg, _ = @reader.recvmsg
|
68
|
+
@serializer.load msg
|
65
69
|
end
|
66
70
|
end
|
67
|
-
|
71
|
+
alias_method :get, :recv
|
68
72
|
end
|
data/lib/iprocess/version.rb
CHANGED
data/test/setup.rb
CHANGED
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: 3.
|
4
|
+
version: 3.2.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-
|
12
|
+
date: 2012-11-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: yard
|
@@ -83,6 +83,7 @@ extra_rdoc_files: []
|
|
83
83
|
files:
|
84
84
|
- .gemtest
|
85
85
|
- .gitignore
|
86
|
+
- .pryrc
|
86
87
|
- .travis.yml
|
87
88
|
- .yardopts
|
88
89
|
- Gemfile
|