ara 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/README.rdoc +19 -0
- data/VERSION +1 -1
- data/ara.gemspec +8 -3
- data/examples/logger_actor.rb +5 -5
- data/examples/pi.rb +70 -0
- data/examples/simple_actor.rb +10 -0
- data/examples/sync_actor.rb +1 -1
- data/lib/ara.rb +1 -0
- data/lib/ara/actor.rb +31 -24
- data/lib/ara/logger.rb +8 -0
- data/lib/ara/routing.rb +65 -0
- data/lib/ara/simple_actor.rb +3 -2
- data/lib/ext/{binding_of_caller.rb → boc.rb} +14 -17
- metadata +24 -11
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -26,6 +26,15 @@ Because of akka[http://akka.io/] and my two parakeets ;)
|
|
26
26
|
sleep rand(10)
|
27
27
|
reply "Thanks @ #{Time.now}!"
|
28
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def pre_start
|
32
|
+
# ...
|
33
|
+
end
|
34
|
+
|
35
|
+
def post_stop
|
36
|
+
# ...
|
37
|
+
end
|
29
38
|
end
|
30
39
|
|
31
40
|
# This method will receive the actor' replies after sending it an asynchronous message
|
@@ -99,6 +108,16 @@ Client :
|
|
99
108
|
|
100
109
|
== Changelog
|
101
110
|
|
111
|
+
=== 0.0.3
|
112
|
+
* Add pre_start and post_stop
|
113
|
+
* Change logger
|
114
|
+
* BindingOfCaller correction
|
115
|
+
* Add Routing
|
116
|
+
|
117
|
+
=== 0.0.2
|
118
|
+
* Add Scheduler support
|
119
|
+
* Add Remote actor support
|
120
|
+
|
102
121
|
=== 0.0.1
|
103
122
|
* Initial version
|
104
123
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/ara.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ara}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Gregoire Lejeune"]
|
12
|
-
s.date = %q{2011-07-
|
12
|
+
s.date = %q{2011-07-17}
|
13
13
|
s.description = %q{Ara is a tiny class that’s allow you to use actors in Ruby}
|
14
14
|
s.email = %q{gregoire.lejeune@free.fr}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
|
|
32
32
|
"examples/async_block.rb",
|
33
33
|
"examples/async_meth.rb",
|
34
34
|
"examples/logger_actor.rb",
|
35
|
+
"examples/pi.rb",
|
35
36
|
"examples/simple_actor.rb",
|
36
37
|
"examples/simple_scheduler.rb",
|
37
38
|
"examples/sync_actor.rb",
|
@@ -45,9 +46,10 @@ Gem::Specification.new do |s|
|
|
45
46
|
"lib/ara/logger.rb",
|
46
47
|
"lib/ara/remote.rb",
|
47
48
|
"lib/ara/remote_actor.rb",
|
49
|
+
"lib/ara/routing.rb",
|
48
50
|
"lib/ara/scheduler.rb",
|
49
51
|
"lib/ara/simple_actor.rb",
|
50
|
-
"lib/ext/
|
52
|
+
"lib/ext/boc.rb",
|
51
53
|
"test/helper.rb",
|
52
54
|
"test/test_ara.rb"
|
53
55
|
]
|
@@ -62,17 +64,20 @@ Gem::Specification.new do |s|
|
|
62
64
|
s.specification_version = 3
|
63
65
|
|
64
66
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
67
|
+
s.add_runtime_dependency(%q<rack>, [">= 1.3.1"])
|
65
68
|
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
66
69
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
67
70
|
s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
|
68
71
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
69
72
|
else
|
73
|
+
s.add_dependency(%q<rack>, [">= 1.3.1"])
|
70
74
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
71
75
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
72
76
|
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
73
77
|
s.add_dependency(%q<rcov>, [">= 0"])
|
74
78
|
end
|
75
79
|
else
|
80
|
+
s.add_dependency(%q<rack>, [">= 1.3.1"])
|
76
81
|
s.add_dependency(%q<shoulda>, [">= 0"])
|
77
82
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
78
83
|
s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
|
data/examples/logger_actor.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
$:.unshift("../lib")
|
2
2
|
require 'ara'
|
3
3
|
|
4
|
-
Ara.logger = Logger.new("actor.log")
|
5
|
-
Ara.
|
4
|
+
# Ara.logger = Logger.new("actor.log")
|
5
|
+
Ara.debug "Starting..."
|
6
6
|
|
7
7
|
class MySimpleActor < SimpleActor
|
8
8
|
def receive( message )
|
9
|
-
Ara.
|
9
|
+
Ara.info "Actor #{self} receive message : #{message}"
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -24,11 +24,11 @@ mySimpleActor.stop
|
|
24
24
|
|
25
25
|
sleep 1
|
26
26
|
|
27
|
-
Ara.
|
27
|
+
Ara.debug "Ending..."
|
28
28
|
|
29
29
|
# This will raise an exception
|
30
30
|
begin
|
31
31
|
mySimpleActor | "Hum..."
|
32
32
|
rescue DeadActor => e
|
33
|
-
|
33
|
+
Ara.fatal e.message
|
34
34
|
end
|
data/examples/pi.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# VERY UNSTABLE !!!
|
2
|
+
|
3
|
+
$:.unshift("../lib")
|
4
|
+
require 'ara'
|
5
|
+
|
6
|
+
class Worker < Actor
|
7
|
+
def calculate_pi_for(start, nb_of_elements)
|
8
|
+
acc = 0.0
|
9
|
+
(start...(start+nb_of_elements)).to_a.each { |i|
|
10
|
+
acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1)
|
11
|
+
}
|
12
|
+
acc
|
13
|
+
end
|
14
|
+
|
15
|
+
def receive(message)
|
16
|
+
r = calculate_pi_for(message[:start], message[:nb_of_elements])
|
17
|
+
reply r
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Master < Actor
|
22
|
+
def receive(message)
|
23
|
+
nb_of_workers = message[:nb_of_workers]
|
24
|
+
nb_of_elements = message[:nb_of_elements]
|
25
|
+
@nb_of_messages = message[:nb_of_messages]
|
26
|
+
|
27
|
+
@pi = 0.0
|
28
|
+
@nb_of_results = 1
|
29
|
+
|
30
|
+
actors = []
|
31
|
+
nb_of_workers.times { |_|
|
32
|
+
actors << Actors.actor_of(Worker).start
|
33
|
+
}
|
34
|
+
|
35
|
+
router = Routing.load_balancer_actor(actors)
|
36
|
+
@m = Mutex.new
|
37
|
+
|
38
|
+
@nb_of_messages.times { |i|
|
39
|
+
sleep 0.002
|
40
|
+
m = { :start => i * nb_of_elements, :nb_of_elements => nb_of_elements }
|
41
|
+
router < m
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def actor_response(message)
|
46
|
+
@m.synchronize {
|
47
|
+
@pi += message
|
48
|
+
Ara.debug("*** Pi estimate : #{@pi}")
|
49
|
+
@nb_of_results += 1
|
50
|
+
self.stop if @nb_of_results >= @nb_of_messages
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def post_stop
|
55
|
+
Ara.debug("Pi estimate : #{@pi}")
|
56
|
+
end
|
57
|
+
|
58
|
+
def pre_start
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def calculate(nb_of_workers, nb_of_elements, nb_of_messages)
|
63
|
+
master = Actors.actor_of(Master).start
|
64
|
+
m = { :nb_of_workers => nb_of_workers, :nb_of_elements => nb_of_elements, :nb_of_messages => nb_of_messages }
|
65
|
+
master | m
|
66
|
+
end
|
67
|
+
|
68
|
+
calculate(10, 1000, 100)
|
69
|
+
|
70
|
+
10.times { sleep 1 }
|
data/examples/simple_actor.rb
CHANGED
@@ -5,6 +5,16 @@ class MySimpleActor < SimpleActor
|
|
5
5
|
def receive( message )
|
6
6
|
puts "Actor #{self} receive message : #{message}"
|
7
7
|
end
|
8
|
+
|
9
|
+
private
|
10
|
+
def pre_start
|
11
|
+
puts "*** in pre_start"
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def post_stop
|
16
|
+
puts "*** in post_stop"
|
17
|
+
end
|
8
18
|
end
|
9
19
|
|
10
20
|
mySimpleActor = Actors.actor_of(MySimpleActor).start
|
data/examples/sync_actor.rb
CHANGED
data/lib/ara.rb
CHANGED
data/lib/ara/actor.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'ext/boc'
|
2
|
+
#require 'ext/binding_of_caller'
|
2
3
|
require 'ara/simple_actor'
|
3
4
|
|
4
5
|
# Actor class
|
@@ -7,6 +8,7 @@ class Actor < SimpleActor
|
|
7
8
|
raise ActorInitializationError, "You can't initialize Actor directly, use Actors.actor_of" if self.class == ::Actor
|
8
9
|
super
|
9
10
|
@main = Queue.new
|
11
|
+
@mutex = Mutex.new
|
10
12
|
end
|
11
13
|
|
12
14
|
# Send a synchronous message
|
@@ -19,7 +21,7 @@ class Actor < SimpleActor
|
|
19
21
|
def <<(message)
|
20
22
|
if @thread.alive?
|
21
23
|
@actorQueue << message
|
22
|
-
@main.
|
24
|
+
@main.shift
|
23
25
|
else
|
24
26
|
raise DeadActor, "Actor is dead!"
|
25
27
|
end
|
@@ -34,28 +36,33 @@ class Actor < SimpleActor
|
|
34
36
|
#
|
35
37
|
# The code after this call will be executed without waiting the actor. You must add a <tt>result</tt> method to get the actor' reponse.
|
36
38
|
def <(message, response_method = nil)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
39
|
+
_actor = self
|
40
|
+
if @thread.alive?
|
41
|
+
@actorQueue << message
|
42
|
+
|
43
|
+
BindingOfCaller.binding_of_caller do |bind|
|
44
|
+
self_of_caller = eval("self", bind)
|
45
|
+
Thread.new do
|
46
|
+
_result = @main.shift
|
47
|
+
begin
|
48
|
+
if block_given?
|
49
|
+
yield _result
|
50
|
+
elsif response_method != nil
|
51
|
+
self_of_caller.send( response_method.to_sym, _result )
|
52
|
+
elsif self_of_caller.respond_to? :actor_response_with_name
|
53
|
+
self_of_caller.send( :actor_response_with_name, _actor, _result )
|
54
|
+
else
|
55
|
+
self_of_caller.send( :actor_response, _result )
|
56
|
+
end
|
57
|
+
rescue => e
|
58
|
+
Ara.fatal(e)
|
59
|
+
raise ActorResponseError, "Error while sending response : #{e}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
else
|
64
|
+
raise DeadActor, "Actor is dead!"
|
65
|
+
end
|
59
66
|
end
|
60
67
|
alias :async_message :<
|
61
68
|
|
data/lib/ara/logger.rb
CHANGED
@@ -10,6 +10,14 @@ module Ara
|
|
10
10
|
L.instance.logger=l
|
11
11
|
end
|
12
12
|
|
13
|
+
def self.method_missing(method_sym, *arguments, &block)
|
14
|
+
if self.logger.respond_to?(method_sym)
|
15
|
+
self.logger.send(method_sym, *arguments)
|
16
|
+
else
|
17
|
+
raise NoMethodError, "undefined method `#{method_sym.to_s}' for Ara:Module"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
13
21
|
class L #:nodoc:
|
14
22
|
include Singleton
|
15
23
|
|
data/lib/ara/routing.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Routing
|
2
|
+
def self.load_balancer_actor(actors)
|
3
|
+
router = Actors.actor_of(Dispatcher).start
|
4
|
+
router | ActorList.new(actors)
|
5
|
+
router
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.Broadcast(message)
|
9
|
+
return B.new(message)
|
10
|
+
end
|
11
|
+
|
12
|
+
class B #:nodoc:
|
13
|
+
def initialize(message)
|
14
|
+
@message = message
|
15
|
+
end
|
16
|
+
|
17
|
+
def message
|
18
|
+
@message
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class ActorList #:nodoc:
|
23
|
+
def initialize(actors)
|
24
|
+
@actors = actors
|
25
|
+
@free_actors = Queue.new
|
26
|
+
@actors.each { |actor| @free_actors << actor }
|
27
|
+
end
|
28
|
+
|
29
|
+
def broadcast(message)
|
30
|
+
@actors.each do |actor|
|
31
|
+
actor | message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_actor
|
36
|
+
@free_actors.shift
|
37
|
+
end
|
38
|
+
|
39
|
+
def release_actor(actor)
|
40
|
+
@free_actors << actor
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Dispatcher < Actor
|
45
|
+
def receive(message)
|
46
|
+
if message.instance_of? Routing::ActorList
|
47
|
+
@list = message
|
48
|
+
elsif message.instance_of? Routing::B
|
49
|
+
@list.broadcast(message.message)
|
50
|
+
else
|
51
|
+
f = @list.get_actor
|
52
|
+
unless f.nil?
|
53
|
+
f < message
|
54
|
+
else
|
55
|
+
Ara.debug("No free actor :(")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def actor_response_with_name(actor, r)
|
61
|
+
@list.release_actor(actor)
|
62
|
+
reply r
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/ara/simple_actor.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'ext/binding_of_caller'
|
2
1
|
require 'ara/exception'
|
3
2
|
|
4
3
|
# This class allow you to create simple actors.
|
@@ -13,9 +12,10 @@ class SimpleActor
|
|
13
12
|
# myActor = Actors.actor_of(MyActor)
|
14
13
|
# myActor.start
|
15
14
|
def start
|
15
|
+
self.send(:pre_start) if self.respond_to?(:pre_start, true)
|
16
16
|
@thread = Thread.new do
|
17
17
|
loop do
|
18
|
-
receive(@actorQueue.
|
18
|
+
receive(@actorQueue.shift)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -29,6 +29,7 @@ class SimpleActor
|
|
29
29
|
# myActor.stop
|
30
30
|
def stop
|
31
31
|
@thread.kill
|
32
|
+
self.send(:post_stop) if self.respond_to?(:post_stop, true)
|
32
33
|
end
|
33
34
|
|
34
35
|
# Send a simple message without expecting any response
|
@@ -23,21 +23,20 @@
|
|
23
23
|
require 'continuation'
|
24
24
|
|
25
25
|
module BindingOfCaller
|
26
|
-
VERSION = "0.1.3"
|
26
|
+
VERSION = "0.1.3"
|
27
27
|
|
28
|
-
module_function
|
28
|
+
# module_function
|
29
29
|
|
30
|
-
def binding_of_caller
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
Thread.current.set_trace_func(nil)
|
38
|
-
case event
|
30
|
+
def self.binding_of_caller
|
31
|
+
cont = nil
|
32
|
+
event_count = 0
|
33
|
+
tracer = lambda do |event, file, line, id, binding, classname|
|
34
|
+
event_count += 1
|
35
|
+
if event_count == 4
|
36
|
+
case event
|
39
37
|
when "return", "line", "end"
|
40
|
-
|
38
|
+
yield binding
|
39
|
+
set_trace_func(nil)
|
41
40
|
else
|
42
41
|
error_msg = "\n" <<
|
43
42
|
"Invalid use of binding_of_caller. One of the following:\n" <<
|
@@ -47,16 +46,14 @@ def binding_of_caller
|
|
47
46
|
" (3) the method using binding_of_caller is called from the\n" <<
|
48
47
|
" last line of a block or global scope.\n" <<
|
49
48
|
"See the documentation for binding_of_caller.\n"
|
50
|
-
cont.call(nil,
|
49
|
+
cont.call(nil, lambda { raise(ScriptError, error_msg) })
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
55
|
-
cont,
|
54
|
+
cont, error = callcc { |cc| cc }
|
56
55
|
if cont
|
57
|
-
|
58
|
-
elsif result
|
59
|
-
yield result
|
56
|
+
set_trace_func(tracer)
|
60
57
|
else
|
61
58
|
error.call
|
62
59
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,23 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-07-
|
12
|
+
date: 2011-07-17 00:00:00.000000000 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
requirement: &2154182500 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.3.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2154182500
|
15
26
|
- !ruby/object:Gem::Dependency
|
16
27
|
name: shoulda
|
17
|
-
requirement: &
|
28
|
+
requirement: &2154182020 !ruby/object:Gem::Requirement
|
18
29
|
none: false
|
19
30
|
requirements:
|
20
31
|
- - ! '>='
|
@@ -22,10 +33,10 @@ dependencies:
|
|
22
33
|
version: '0'
|
23
34
|
type: :development
|
24
35
|
prerelease: false
|
25
|
-
version_requirements: *
|
36
|
+
version_requirements: *2154182020
|
26
37
|
- !ruby/object:Gem::Dependency
|
27
38
|
name: bundler
|
28
|
-
requirement: &
|
39
|
+
requirement: &2154181540 !ruby/object:Gem::Requirement
|
29
40
|
none: false
|
30
41
|
requirements:
|
31
42
|
- - ~>
|
@@ -33,10 +44,10 @@ dependencies:
|
|
33
44
|
version: 1.0.0
|
34
45
|
type: :development
|
35
46
|
prerelease: false
|
36
|
-
version_requirements: *
|
47
|
+
version_requirements: *2154181540
|
37
48
|
- !ruby/object:Gem::Dependency
|
38
49
|
name: jeweler
|
39
|
-
requirement: &
|
50
|
+
requirement: &2154181060 !ruby/object:Gem::Requirement
|
40
51
|
none: false
|
41
52
|
requirements:
|
42
53
|
- - ~>
|
@@ -44,10 +55,10 @@ dependencies:
|
|
44
55
|
version: 1.6.2
|
45
56
|
type: :development
|
46
57
|
prerelease: false
|
47
|
-
version_requirements: *
|
58
|
+
version_requirements: *2154181060
|
48
59
|
- !ruby/object:Gem::Dependency
|
49
60
|
name: rcov
|
50
|
-
requirement: &
|
61
|
+
requirement: &2154180580 !ruby/object:Gem::Requirement
|
51
62
|
none: false
|
52
63
|
requirements:
|
53
64
|
- - ! '>='
|
@@ -55,7 +66,7 @@ dependencies:
|
|
55
66
|
version: '0'
|
56
67
|
type: :development
|
57
68
|
prerelease: false
|
58
|
-
version_requirements: *
|
69
|
+
version_requirements: *2154180580
|
59
70
|
description: Ara is a tiny class that’s allow you to use actors in Ruby
|
60
71
|
email: gregoire.lejeune@free.fr
|
61
72
|
executables: []
|
@@ -79,6 +90,7 @@ files:
|
|
79
90
|
- examples/async_block.rb
|
80
91
|
- examples/async_meth.rb
|
81
92
|
- examples/logger_actor.rb
|
93
|
+
- examples/pi.rb
|
82
94
|
- examples/simple_actor.rb
|
83
95
|
- examples/simple_scheduler.rb
|
84
96
|
- examples/sync_actor.rb
|
@@ -92,9 +104,10 @@ files:
|
|
92
104
|
- lib/ara/logger.rb
|
93
105
|
- lib/ara/remote.rb
|
94
106
|
- lib/ara/remote_actor.rb
|
107
|
+
- lib/ara/routing.rb
|
95
108
|
- lib/ara/scheduler.rb
|
96
109
|
- lib/ara/simple_actor.rb
|
97
|
-
- lib/ext/
|
110
|
+
- lib/ext/boc.rb
|
98
111
|
- test/helper.rb
|
99
112
|
- test/test_ara.rb
|
100
113
|
has_rdoc: true
|