legion 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b4b0225245d1e96a8c1a1c67525ccbc4c016c108
4
+ data.tar.gz: 2d9a10ccffecd74598e2608fa97c45f191aa01ca
5
+ SHA512:
6
+ metadata.gz: c637b4f433b0f0081f5158d014ab80986576d8375ef748fd3e3b0d35508d504b990629ce267ab5aa04b78396c1d567233ff5134f309284b71b849f91b856fabc
7
+ data.tar.gz: 72168bc261d81feded3b4fa9b1d4b501747e255cd2ae3762ccca0a9541a4b164a910c273b94ff3d0cfabdcb7aab8885e676006c69525a43e9e3e1af2135a13b4
@@ -0,0 +1,10 @@
1
+ require_relative "legion/version"
2
+ require_relative "legion/object"
3
+ require_relative "legion/supervisor"
4
+ require "pry"
5
+ require "pry-debugger"
6
+
7
+ module Legion
8
+ end
9
+
10
+
@@ -0,0 +1,57 @@
1
+ require "drb"
2
+ require "monitor"
3
+ require "socket"
4
+
5
+ module Legion
6
+ class Object
7
+ include MonitorMixin
8
+
9
+ attr_reader :pid, :uri
10
+
11
+ class << self
12
+ def method_added(name)
13
+ return if name =~ /_async\z/i
14
+ define_method "#{name}_async" do |*args|
15
+ Thread.new do
16
+ synchronize { @busy = true }
17
+ self.class.callbacks[:before][name].call unless self.class.callbacks[:before][name].nil?
18
+ send(name, *args)
19
+ synchronize { @busy = false }
20
+ Thread.terminate
21
+ end
22
+ end
23
+ end
24
+
25
+ def callbacks
26
+ @callbacks ||= {before: {}}
27
+ end
28
+
29
+ def before(name, &block)
30
+ callbacks[:before][name] = block
31
+ end
32
+ end
33
+
34
+ def ok?
35
+ true
36
+ end
37
+
38
+ def busy?
39
+ !!@busy
40
+ end
41
+
42
+ def start_remote_instance(port: nil)
43
+ return unless pid.nil?
44
+ @uri = "druby://localhost:#{port}"
45
+ @pid = fork do
46
+ DRb.start_service uri, self
47
+ DRb.thread.join
48
+ end
49
+ Process.detach pid
50
+ end
51
+
52
+ def exit
53
+ DRb.stop_service
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,63 @@
1
+ require "drb"
2
+
3
+ module Legion
4
+ class Supervisor
5
+ attr_reader(
6
+ :klass,
7
+ :processes,
8
+ :local_instances,
9
+ :remote_instances
10
+ )
11
+
12
+ def initialize(klass, processes: 1)
13
+ @klass = klass
14
+ @processes = processes
15
+ @local_instances = []
16
+ @remote_instances = []
17
+ end
18
+
19
+ def start_remote_instances(port: nil)
20
+ DRb.start_service
21
+ (1..processes).each do |i|
22
+ local_instance = klass.new
23
+ local_instance.start_remote_instance(port: port)
24
+ port += 1
25
+ local_instances << local_instance
26
+ remote_instance = DRbObject.new_with_uri(local_instance.uri)
27
+ verify_remote_instance(remote_instance)
28
+ remote_instances << remote_instance
29
+ end
30
+ end
31
+
32
+ def stop_remote_instances
33
+ remote_instances.each do |remote_instance|
34
+ remote_instance.exit rescue nil
35
+ end
36
+ DRb.stop_service
37
+ end
38
+
39
+ def get_remote_instance
40
+ @remote_instance_index ||= 0
41
+ remote_instance = remote_instances[@remote_instance_index]
42
+ sleep 0.01 while remote_instance.busy?
43
+ @remote_instance_index += 1
44
+ @remote_instance_index = 0 if @remote_instance_index >= remote_instances.length
45
+ remote_instance
46
+ end
47
+
48
+ protected
49
+
50
+ def verify_remote_instance(remote_instance)
51
+ ok = false
52
+ while !ok
53
+ begin
54
+ ok = remote_instance.ok?
55
+ rescue DRb::DRbConnError
56
+ sleep 0.1
57
+ end
58
+ end
59
+ ok
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,3 @@
1
+ module Legion
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "../lib/legion"
2
+
3
+ class Example < Legion::Object
4
+
5
+ def work(index)
6
+ sleep 2
7
+ end
8
+
9
+ before :work do
10
+ puts "before work"
11
+ end
12
+
13
+ end
14
+
15
+ def run_example
16
+ supervisor = Legion::Supervisor.new(Example, processes: 7)
17
+ supervisor.start_remote_instances(port: 42042)
18
+
19
+ 1000.times do |i|
20
+ worker = supervisor.get_remote_instance
21
+ worker.work_async(i)
22
+ puts i
23
+ end
24
+
25
+ supervisor.stop_remote_instances
26
+ end
27
+
28
+ run_example
29
+
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: legion
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Hopkins
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-05 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: True concurrent processing power made easy... even for MRI.
42
+ email:
43
+ - natehop@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/legion/object.rb
49
+ - lib/legion/supervisor.rb
50
+ - lib/legion/version.rb
51
+ - lib/legion.rb
52
+ - test/example.rb
53
+ homepage: https://github.com/hopsoft/legion
54
+ licenses:
55
+ - MIT
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 2.0.3
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: True concurrent processing power made easy... even for MRI.
77
+ test_files:
78
+ - test/example.rb
79
+ has_rdoc: