iprocess 1.0.8 → 2.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
@@ -10,42 +10,36 @@ __OVERVIEW__
10
10
 
11
11
  __DESCRIPTION__
12
12
 
13
- IProcess, short for _Inter Process Communication(IPC) Process_, is a
14
- Domain Specific Language(DSL) that you can use to share Ruby objects
15
- between processes on UNIX-like operating systems. The README covers the
16
- basics, and there is the API documentation for everything else.
17
-
18
- This project was formerly known as 'Barney'.
13
+ IProcess, short for _Inter Process Communication(IPC) Process_, is a collection
14
+ of classes you can use to transport Ruby objects between processes running on
15
+ UNIX-like operating systems.
19
16
 
20
17
  __EXAMPLES__
21
18
 
22
19
  __1.__
23
20
 
24
- Sequential in nature (each subprocess must finish before another can execute):
21
+ A single subprocess is spawned:
22
+
23
+ message = IProcess.spawn { [:yes, :no] }
24
+ p message # => [[:yes, :no]]
25
25
 
26
- name = "rob"
26
+ __2.__
27
27
 
28
- IProcess.new do
29
- share :name
30
-
31
- fork do
32
- name.capitalize!
33
- end
34
- end
28
+ A unit of work does not need to be a block, though, and the number of
29
+ subprocesses you can spawn is variable (5, in this example):
35
30
 
36
- p name # => "Rob"
37
-
38
- __2.__
31
+ class Worker
32
+ def initialize
33
+ @num = 1
34
+ end
39
35
 
40
- A subprocess is spawned 5 times, in parallel:
36
+ def call
37
+ @num + 1
38
+ end
39
+ end
41
40
 
42
- workload =
43
- IProcess::Job.spawn(5) {
44
- # Replace this with heavily CPU-bound code ;-)
45
- 1 + 1
46
- }
41
+ IProcess.spawn(5, Worker.new) # => [2, 2, 2, 2, 2]
47
42
 
48
- p workload # [2, 2, 2, 2, 2]
49
43
 
50
44
  __PLATFORM SUPPORT__
51
45
 
data/iprocess.gemspec CHANGED
@@ -7,7 +7,7 @@ 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 = 'A Domain Specific Language(DSL) for sharing Ruby objects' \
10
+ s.summary = 'A set of classes you can use to transport ruby objects ' \
11
11
  'between processes on UNIX-like operating systems.'
12
12
  s.description = s.summary
13
13
 
data/lib/iprocess/job.rb CHANGED
@@ -1,75 +1,5 @@
1
1
  class IProcess::Job
2
2
 
3
- #
4
- # @overload spawn(number_of_jobs = 1, worker)
5
- #
6
- # Spawn one or more jobs to be run in parallel.
7
- #
8
- # @param [Integer] number_of_jobs
9
- # The number of jobs to spawn.
10
- #
11
- # @param [#call] worker
12
- # The unit of work to execute in one or more jobs.
13
- #
14
- # @return [Array<Object>]
15
- # The return value of one or more workers.
16
- #
17
- def self.spawn number_of_jobs = 1, obj = nil, &worker
18
- worker = obj || worker
19
3
 
20
- jobs =
21
- Array.new(number_of_jobs) do
22
- job = IProcess::Job.new(worker)
23
- job.execute
24
- job
25
- end
26
-
27
- jobs.map do |job|
28
- job.result
29
- end
30
- end
31
-
32
- #
33
- # @param [#call] worker
34
- # The unit of work to execute in a subprocess.
35
- #
36
- # @raise [ArgumentError]
37
- # If a worker is not given.
38
- #
39
- # @return [IProcess::Job]
40
- # Returns self.
41
- #
42
- def initialize worker
43
- @worker = worker
44
- @channel = nil
45
- @pid = nil
46
-
47
- unless @worker.respond_to?(:call)
48
- raise ArgumentError,
49
- "Expected worker to implement #{@worker.class}#call"
50
- end
51
- end
52
-
53
- #
54
- # Executes a unit of work in a subprocess.
55
- #
56
- # @return [Fixnum]
57
- # The process ID of the spawned subprocess.
58
- #
59
- def execute
60
- @channel = IProcess::Channel.new
61
- @pid = fork { @channel.write(@worker.call) }
62
- end
63
-
64
- #
65
- # @return [Object]
66
- # Returns the return value of the unit of work.
67
- #
68
- def result
69
- Process.wait(@pid)
70
- @channel.recv
71
- end
72
4
 
73
5
  end
74
-
75
-
@@ -1,3 +1,3 @@
1
1
  class IProcess
2
- VERSION = '1.0.8'
2
+ VERSION = '2.0.0'
3
3
  end
data/lib/iprocess.rb CHANGED
@@ -1,97 +1,75 @@
1
1
  class IProcess
2
2
 
3
- require 'set'
4
3
  require_relative 'iprocess/version'
5
4
  require_relative 'iprocess/channel'
6
- require_relative 'iprocess/job'
7
- require_relative 'iprocess/delegator'
8
-
5
+
6
+ #
7
+ # @overload spawn(number_of_jobs = 1, worker)
8
+ #
9
+ # Spawn one or more jobs to be run in parallel.
10
+ #
11
+ # @param [Integer] number_of_jobs
12
+ # The number of jobs to spawn.
9
13
  #
10
- # @return [IProcess]
14
+ # @param [#call] worker
15
+ # The unit of work to execute in one or more jobs.
11
16
  #
12
- def initialize &block
13
- @variables = SortedSet.new
14
- @scope = nil
17
+ # @return [Array<Object>]
18
+ # The return value of one or more workers.
19
+ #
20
+ def self.spawn(number_of = 1, obj = nil, &worker)
21
+ worker = obj || worker
15
22
 
16
- if block_given?
17
- @scope = block.binding
18
- IProcess::Delegator.new(self).instance_eval(&block)
23
+ jobs =
24
+ Array.new(number_of) do
25
+ job = IProcess.new(worker)
26
+ job.execute
27
+ job
19
28
  end
20
- end
21
29
 
22
- #
23
- # @return [Array<Symbol>]
24
- # Returns a list of shared variables.
25
- #
26
- def variables
27
- @variables.to_a
30
+ jobs.map do |job|
31
+ job.result
32
+ end
28
33
  end
29
34
 
30
35
  #
31
- # Marks a variable or constant to be shared between two processes.
36
+ # @param [#call] worker
37
+ # The unit of work to execute in a subprocess.
32
38
  #
33
- # @param [Array<#to_sym>] variables
34
- # Accepts the name(s) of the variables or constants to share.
39
+ # @raise [ArgumentError]
40
+ # If a worker is not given.
35
41
  #
36
- # @return [Array<Symbol>]
37
- # Returns a list of all variables that are being shared.
42
+ # @return [IProcess::Job]
43
+ # Returns self.
38
44
  #
39
- def share *variables
40
- @variables.merge variables.map(&:to_sym)
41
- @variables.to_a
45
+ def initialize(worker)
46
+ @worker = worker
47
+ @channel = nil
48
+ @pid = nil
49
+
50
+ unless @worker.respond_to?(:call)
51
+ raise ArgumentError,
52
+ "Expected worker to implement #{@worker.class}#call"
53
+ end
42
54
  end
43
55
 
44
56
  #
45
- # Removes a variable or constant from being shared between two processes.
46
- #
47
- # @param [Array<#to_sym>] variables
48
- # Accepts the name(s) of the variables or constants to stop sharing.
57
+ # Executes a unit of work in a subprocess.
49
58
  #
50
- # @return [Array<Symbol>]
51
- # Returns a list of the variables that are still being shared.
59
+ # @return [Fixnum]
60
+ # The process ID of the spawned subprocess.
52
61
  #
53
- def unshare *variables
54
- @variables.subtract variables.map(&:to_sym)
55
- @variables.to_a
62
+ def execute
63
+ @channel = IProcess::Channel.new
64
+ @pid = fork { @channel.write(@worker.call) }
56
65
  end
57
66
 
58
67
  #
59
- # Spawns a subprocess.
60
- # The subprocess is waited on via Process.wait().
68
+ # @return [Object]
69
+ # Returns the return value of the unit of work.
61
70
  #
62
- # @param [Proc] &block
63
- # A block executed within a subprocess.
64
- #
65
- # @raise [ArgumentError]
66
- # If no block is given.
67
- #
68
- # @return [Fixnum]
69
- # The Process ID(PID) of the subprocess.
70
- #
71
- def fork &block
72
- unless block_given?
73
- raise ArgumentError, "Wrong number of arguments (0 for 1)"
74
- end
75
-
76
- scope = @scope || block.binding
77
- channels = @variables.map { |name| IProcess::Channel.new(name) }
78
-
79
- pid = Kernel.fork do
80
- scope.eval("self").instance_eval(&block)
81
- channels.each do |channel|
82
- channel.write scope.eval(channel.name.to_s)
83
- end
84
- end
85
-
86
- Process.wait(pid)
87
-
88
- channels.each do |channel|
89
- Thread.current[:__iprocess_obj__] = channel.recv
90
- scope.eval("#{channel.name} = Thread.current[:__iprocess_obj__]")
91
- end
92
-
93
- Thread.current[:__iprocess_obj__] = nil
94
- pid
71
+ def result
72
+ Process.wait(@pid)
73
+ @channel.recv
95
74
  end
96
-
97
75
  end
@@ -1,109 +1,26 @@
1
1
  context IProcess do
2
-
3
- context 'initialize' do
4
- it 'calls a block, if given.' do
5
- mock = MiniTest::Mock.new
6
- mock.expect :ok, nil
7
-
8
- IProcess.new do
9
- mock.ok
10
- end
11
-
12
- mock.verify
13
- end
14
- end
15
-
16
- context 'share' do
17
- it 'shares a variable.' do
18
- IProcess.new do
19
- share :a
20
- variables.must_equal [:a]
21
- end
22
- end
23
-
24
- it "does not store duplicate variables" do
25
- IProcess.new do
26
- share :a, :a
27
- variables.must_equal [:a]
28
- end
29
- end
30
- end
31
-
32
- context 'unshare' do
33
- it "unshares a variable." do
34
- IProcess.new do
35
- share :a
36
- unshare :a
37
- variables.must_be_empty
38
- end
39
- end
40
- end
41
-
42
- context 'fork' do
43
- it 'returns the Process ID(PID) on success.' do
44
- pid = IProcess.new.fork { }
45
- assert_equal Fixnum, pid.class
46
- end
47
-
48
- it 'raises if no block is given.' do
49
- obj = IProcess.new
50
-
51
- assert_raises(ArgumentError) do
52
- obj.fork
53
- end
2
+ context 'spawn' do
3
+ it 'spawns two Proc workers.' do
4
+ topic = IProcess.spawn(2) { :ok }
5
+ topic.must_equal([:ok, :ok])
54
6
  end
55
7
 
56
- it 'synchronizes a shared variable.' do
57
- local = 1
58
-
59
- IProcess.new do
60
- share :local
61
- fork { local = 2 }
62
- end
63
-
64
- local.must_equal(2)
65
- end
66
-
67
- it 'synchronizes two shared variables.' do
68
- local1, local2 = 1, 2
69
-
70
- IProcess.new do
71
- share :local1, :local2
72
-
73
- fork do
74
- local1 = 5
75
- local2 = 9
8
+ it 'spawns two non-Proc workers.' do
9
+ worker =
10
+ Class.new do
11
+ def call
12
+ :ok
76
13
  end
77
14
  end
78
15
 
79
- local1.must_equal(5)
80
- local2.must_equal(9)
16
+ topic = IProcess.spawn(2, worker.new)
17
+ topic.must_equal([:ok, :ok])
81
18
  end
19
+ end
82
20
 
83
- it 'synchronizes a instance variable.' do
84
- @ivar = :ivar
85
-
86
- IProcess.new do
87
- share :@ivar
88
-
89
- fork do
90
- @ivar = 2
91
- end
92
- end
93
-
94
- @ivar.must_equal(2)
95
- end
96
-
97
- it 'provide access to surrounding local variables.' do
98
- local = :local
99
-
100
- IProcess.new do
101
- fork do
102
- local.must_equal(:local)
103
- end
104
- end
21
+ context 'initialize' do
22
+ it "raises if given an object who cannot respond to #call." do
23
+ proc { IProcess.new(nil) }.must_raise(ArgumentError)
105
24
  end
106
25
  end
107
-
108
26
  end
109
-
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: 1.0.8
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-18 00:00:00.000000000 Z
12
+ date: 2012-04-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yard
16
- requirement: &70341456473680 !ruby/object:Gem::Requirement
16
+ requirement: &12570880 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0.7'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70341456473680
24
+ version_requirements: *12570880
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: redcarpet
27
- requirement: &70341456471200 !ruby/object:Gem::Requirement
27
+ requirement: &12570400 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '1.17'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70341456471200
35
+ version_requirements: *12570400
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: minitest
38
- requirement: &70341456462240 !ruby/object:Gem::Requirement
38
+ requirement: &12569880 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '2.6'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70341456462240
46
+ version_requirements: *12569880
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rake
49
- requirement: &70341456460660 !ruby/object:Gem::Requirement
49
+ requirement: &12569380 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,8 +54,8 @@ dependencies:
54
54
  version: 0.9.2
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70341456460660
58
- description: A Domain Specific Language(DSL) for sharing Ruby objectsbetween processes
57
+ version_requirements: *12569380
58
+ description: A set of classes you can use to transport ruby objects between processes
59
59
  on UNIX-like operating systems.
60
60
  email: rob@flowof.info
61
61
  executables: []
@@ -73,11 +73,9 @@ files:
73
73
  - iprocess.gemspec
74
74
  - lib/iprocess.rb
75
75
  - lib/iprocess/channel.rb
76
- - lib/iprocess/delegator.rb
77
76
  - lib/iprocess/job.rb
78
77
  - lib/iprocess/version.rb
79
78
  - test/setup.rb
80
- - test/test_IProcess_Job_class.rb
81
79
  - test/test_IProcess_class.rb
82
80
  homepage: https://github.com/robgleeson/iprocess
83
81
  licenses: []
@@ -102,10 +100,9 @@ rubyforge_project: ! '[none]'
102
100
  rubygems_version: 1.8.11
103
101
  signing_key:
104
102
  specification_version: 3
105
- summary: A Domain Specific Language(DSL) for sharing Ruby objectsbetween processes
103
+ summary: A set of classes you can use to transport ruby objects between processes
106
104
  on UNIX-like operating systems.
107
105
  test_files:
108
- - test/setup.rb
109
106
  - test/test_IProcess_class.rb
110
- - test/test_IProcess_Job_class.rb
107
+ - test/setup.rb
111
108
  has_rdoc:
@@ -1,55 +0,0 @@
1
- class IProcess::Delegator
2
-
3
- #
4
- # @param [IProcess] delegate
5
- # An instance of {IProcess}.
6
- #
7
- def initialize delegate
8
- @__delegate__ = delegate
9
- end
10
-
11
- #
12
- # @param
13
- # (see IProcess#share)
14
- #
15
- # @return
16
- # (see IProcess#share)
17
- #
18
- def share *args
19
- @__delegate__.share *args
20
- end
21
-
22
- #
23
- # @param
24
- # (see IProcess#unshare)
25
- #
26
- # @return
27
- # (see IProcess#unshare)
28
- #
29
- def unshare *args
30
- @__delegate__.unshare *args
31
- end
32
-
33
- #
34
- # @return
35
- # (see IProcess#variables)
36
- #
37
- def variables
38
- @__delegate__.variables
39
- end
40
-
41
- #
42
- # @param
43
- # (see IProcess#fork)
44
- #
45
- # @raise
46
- # (see IProcess#fork)
47
- #
48
- # @return
49
- # (see IProcess#fork)
50
- #
51
- def fork(&block)
52
- @__delegate__.fork(&block)
53
- end
54
-
55
- end
@@ -1,27 +0,0 @@
1
- context IProcess::Job do
2
- context 'spawn' do
3
- it 'spawns two Proc workers.' do
4
- topic = IProcess::Job.spawn(2) { :ok }
5
- topic.must_equal([:ok, :ok])
6
- end
7
-
8
- it 'spawns two non-Proc workers.' do
9
- worker =
10
- Class.new do
11
- def call
12
- :ok
13
- end
14
- end
15
-
16
- topic = IProcess::Job.spawn(2, worker.new)
17
- topic.must_equal([:ok, :ok])
18
- end
19
- end
20
-
21
- context 'initialize' do
22
- it "raises if given an object who cannot respond to #call." do
23
- proc { IProcess::Job.new(nil) }.must_raise(ArgumentError)
24
- end
25
- end
26
- end
27
-