pb_actor 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7b680bcef360e5d1e59a276d633ceb22aee7f496
4
+ data.tar.gz: cd56e2019501bf107915673daf02c4733711d6b4
5
+ SHA512:
6
+ metadata.gz: b984d664769c243b51738419ea67d4363a61716ea6e321403225e80eee72d74c4f012fa540b4d76b37ac44d1c4cef8cd5d33e062580da149be54f933ed8940a2
7
+ data.tar.gz: 71aed55f5256e8f56544162e812863829b209f5494107927a41d35ed9037e2bcf74295ad1025706d46cf9af588e198609109d767866cffcef10ebdac600d4f6f
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rspec'
4
+
5
+ # Specify your gem's dependencies in pb_actor.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # PbActor
2
+
3
+ Process based Actor.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'pb_actor'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install pb_actor
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ require 'pb_actor'
23
+
24
+ class Test
25
+ include PbActor
26
+ def fib(n)
27
+ if n < 2
28
+ 1
29
+ else
30
+ fib(n - 1) + fib(n - 2)
31
+ end
32
+ end
33
+
34
+ def p_fib(n)
35
+ puts fib(n)
36
+ end
37
+ end
38
+
39
+ f = Test.new
40
+ #=> <PbActor::Proxy:0x00000002106448 @origin=#<Test:0x00000002106470>, @pid=23487, @rd=#<IO:fd 7>, @wr=#<IO:fd 10>>
41
+
42
+ f.alive?
43
+ #=> true
44
+
45
+ f.fib(30)
46
+ #=> 1346269
47
+
48
+ f.async.p_fib(30)
49
+ #=> nil
50
+ # 1346269
51
+
52
+ f.terminate
53
+ f.alive?
54
+ #=> false
55
+ ```
56
+
57
+ ## Contributing
58
+
59
+ 1. Fork it
60
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
61
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
62
+ 4. Push to the branch (`git push origin my-new-feature`)
63
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
5
+ task :default => :spec
@@ -0,0 +1,110 @@
1
+ require 'timeout'
2
+
3
+ module PbActor
4
+ class DeadActorError < StandardError
5
+ end
6
+
7
+ class BasicProxy
8
+ module Message
9
+ class << self
10
+ def send msg, wr
11
+ Marshal.dump(msg, wr)
12
+ rescue Errno::EPIPE => e
13
+ raise DeadActorError, 'dead actor call'
14
+ end
15
+
16
+ def recv rd
17
+ Marshal.load rd
18
+ end
19
+ end
20
+ end
21
+
22
+ def alive?
23
+ begin
24
+ # Have any other way to check a process status?
25
+ timeout(0.001){Process.wait}
26
+ rescue Timeout::Error => e
27
+ end
28
+ Process.kill(0, @pid) == 1
29
+ rescue Errno::ESRCH, Errno::ECHILD => e
30
+ false
31
+ end
32
+
33
+ def method_missing method, *args, &blk
34
+ raise ArgumentError, 'actor not support block' if blk
35
+ raise DeadActorError, 'dead actor call' unless alive?
36
+ end
37
+
38
+ def to_s
39
+ "#{self.class}(#{@origin.class})"
40
+ end
41
+
42
+ undef send, public_send
43
+ end
44
+
45
+ class Proxy < BasicProxy
46
+ def initialize origin
47
+ @origin = origin
48
+ pr, cw = IO.pipe
49
+ cr, pw = IO.pipe
50
+ @pid = fork do
51
+ [pr, pw].each &:close
52
+ loop do
53
+ type, method, *args = Message.recv cr
54
+ case type
55
+ when :method_call, :async_method_call
56
+ value = @origin.public_send method, *args
57
+ Message.send([:return_value, value], cw) if type == :method_call
58
+ when :terminate
59
+ exit
60
+ else
61
+ raise "what happend!? receive #{type.inspect}"
62
+ end
63
+ end
64
+ end
65
+ [cr, cw].each &:close
66
+ @rd = pr
67
+ @wr = pw
68
+ end
69
+
70
+ def method_missing method, *args, &blk
71
+ super
72
+ Message.send([:method_call, method, *args], @wr)
73
+ type, value = Message.recv @rd
74
+ case type
75
+ when :return_value
76
+ value
77
+ else
78
+ raise "what happend!? receive #{type}"
79
+ end
80
+ end
81
+
82
+ def async
83
+ AsyncProxy.new @origin, @pid, @wr
84
+ end
85
+
86
+ def terminate
87
+ Message.send [:terminate], @wr
88
+ Process.wait @pid
89
+ nil
90
+ end
91
+
92
+ def terminate!
93
+ Process.kill "KILL", @pid
94
+ Process.wait @pid
95
+ nil
96
+ end
97
+ end
98
+
99
+ class AsyncProxy < BasicProxy
100
+ def initialize origin, pid, wr
101
+ @origin, @pid, @wr = origin, pid, wr
102
+ end
103
+
104
+ def method_missing method, *args, &blk
105
+ super
106
+ Message.send [:async_method_call, method, *args], @wr
107
+ nil
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,3 @@
1
+ module PbActor
2
+ VERSION = "0.0.1"
3
+ end
data/lib/pb_actor.rb ADDED
@@ -0,0 +1,24 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "pb_actor/version"
3
+ require "pb_actor/proxy"
4
+
5
+ module PbActor
6
+ class << self
7
+ def included base
8
+ base.send :include, InstanceMethods
9
+ base.send :extend, ClassMethods
10
+ end
11
+ end
12
+
13
+ module ClassMethods
14
+ def new *args, &blk
15
+ origin = allocate
16
+ proxy = Proxy.new origin
17
+ proxy.async.send :initialize, *args, &blk
18
+ proxy
19
+ end
20
+ end
21
+
22
+ module InstanceMethods
23
+ end
24
+ end
data/pb_actor.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pb_actor/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pb_actor"
8
+ spec.version = PbActor::VERSION
9
+ spec.authors = ["jjy"]
10
+ spec.email = ["jjyruby@gmail.com"]
11
+ spec.description = %q{Process based Actor.}
12
+ spec.summary = %q{Just for fun.}
13
+ spec.homepage = "https://github.com/jjyr/pb_actor"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ class Test
4
+ include PbActor
5
+
6
+ attr_accessor :foo, :bar
7
+
8
+ def initialize foo
9
+ self.foo = foo
10
+ end
11
+
12
+ def hello something
13
+ "hello #{something}"
14
+ end
15
+ end
16
+
17
+ describe PbActor do
18
+ before :each do
19
+ @test = Test.new 'foo'
20
+ end
21
+
22
+ after :each do
23
+ @test.terminate! if @test && @test.alive?
24
+ end
25
+
26
+ it 'initialize should work' do
27
+ wait_until do
28
+ @test.foo
29
+ end
30
+ @test.foo.should == 'foo'
31
+ end
32
+
33
+ it 'pass block should raise error' do
34
+ expect do
35
+ @test.hello('world') do
36
+ 'nothing'
37
+ end
38
+ end.to raise_error(ArgumentError)
39
+ end
40
+
41
+ it 'sync call should work' do
42
+ @test.hello('actor').should == 'hello actor'
43
+ end
44
+
45
+ it 'async call should work' do
46
+ @test.async.bar= 'bar'
47
+ wait_until do
48
+ @test.bar
49
+ end
50
+ @test.bar.should == 'bar'
51
+ end
52
+
53
+ it 'terminate should work' do
54
+ @test.alive?.should == true
55
+ @test.terminate
56
+ @test.alive?.should == false
57
+ expect{@test.foo}.to raise_error(PbActor::DeadActorError)
58
+ end
59
+
60
+ it 'terminate! should work' do
61
+ @test.alive?.should == true
62
+ @test.terminate!
63
+ wait_until do
64
+ @test.alive? == false
65
+ end
66
+ @test.alive?.should == false
67
+ end
68
+
69
+ it 'to_s should correct' do
70
+ @test.to_s.should == 'PbActor::Proxy(Test)'
71
+ @test.async.to_s.should == 'PbActor::AsyncProxy(Test)'
72
+ end
73
+ end
@@ -0,0 +1,7 @@
1
+ require 'pb_actor'
2
+
3
+ def wait_until wait_time = 3
4
+ timeout wait_time do
5
+ sleep 0.1 until yield
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pb_actor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - jjy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Process based Actor.
42
+ email:
43
+ - jjyruby@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - lib/pb_actor.rb
54
+ - lib/pb_actor/proxy.rb
55
+ - lib/pb_actor/version.rb
56
+ - pb_actor.gemspec
57
+ - spec/pb_actor_spec.rb
58
+ - spec/spec_helper.rb
59
+ homepage: https://github.com/jjyr/pb_actor
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.0.5
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Just for fun.
83
+ test_files:
84
+ - spec/pb_actor_spec.rb
85
+ - spec/spec_helper.rb