iprocess 1.0.8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
-