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 CHANGED
@@ -2,6 +2,7 @@ source "http://rubygems.org"
2
2
  # Add dependencies required to use your gem here.
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
+ gem "rack", ">= 1.3.1"
5
6
 
6
7
  # Add dependencies to develop your gem here.
7
8
  # Include everything needed to run rake, tests, features, etc.
@@ -6,6 +6,7 @@ GEM
6
6
  bundler (~> 1.0)
7
7
  git (>= 1.2.5)
8
8
  rake
9
+ rack (1.3.1)
9
10
  rake (0.9.2)
10
11
  rcov (0.9.9)
11
12
  shoulda (2.11.3)
@@ -16,5 +17,6 @@ PLATFORMS
16
17
  DEPENDENCIES
17
18
  bundler (~> 1.0.0)
18
19
  jeweler (~> 1.6.2)
20
+ rack (>= 1.3.1)
19
21
  rcov
20
22
  shoulda
@@ -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.2
1
+ 0.0.3
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ara}
8
- s.version = "0.0.2"
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-15}
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/binding_of_caller.rb",
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"])
@@ -1,12 +1,12 @@
1
1
  $:.unshift("../lib")
2
2
  require 'ara'
3
3
 
4
- Ara.logger = Logger.new("actor.log")
5
- Ara.logger.debug "Starting..."
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.logger.debug "Actor #{self} receive message : #{message}"
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.logger.debug "Ending..."
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
- puts e
33
+ Ara.fatal e.message
34
34
  end
@@ -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 }
@@ -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
@@ -3,7 +3,7 @@ require 'ara'
3
3
 
4
4
  class MySynchronizedActor < Actor
5
5
  def receive(message)
6
- puts "Actor #{self} receive message : #{message}"
6
+ puts "Actor #{self} receive message : #{message} and take a break..."
7
7
  sleep rand(10)
8
8
  reply "Thanks @ #{Time.now}!"
9
9
  end
data/lib/ara.rb CHANGED
@@ -8,3 +8,4 @@ require 'ara/actors'
8
8
  require 'ara/scheduler'
9
9
 
10
10
  require 'ara/remote'
11
+ require 'ara/routing'
@@ -1,4 +1,5 @@
1
- require 'ara/exception'
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.pop
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
- if @thread.alive?
38
- @actorQueue << message
39
- BindingOfCaller.binding_of_caller do |bind|
40
- self_of_caller = eval("self", bind)
41
- Thread.new do
42
- _result = @main.pop
43
- begin
44
- if block_given?
45
- yield _result
46
- elsif response_method != nil
47
- self_of_caller.send( response_method.to_sym, _result )
48
- else
49
- self_of_caller.send( :actor_response, _result )
50
- end
51
- rescue => e
52
- raise ActorResponseError, "Error while sending response : #{e}"
53
- end
54
- end
55
- end
56
- else
57
- raise DeadActor, "Actor is dead!"
58
- end
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
 
@@ -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
 
@@ -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
@@ -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.pop)
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
- cont = nil
32
- event_count = 0
33
-
34
- tracer = lambda do |event, _, _, _, binding, _|
35
- event_count += 1
36
- if event_count == 4
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
- cont.call(nil, binding)
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, nil, lambda { raise(ScriptError, error_msg) })
49
+ cont.call(nil, lambda { raise(ScriptError, error_msg) })
51
50
  end
52
51
  end
53
52
  end
54
53
 
55
- cont, result, error = callcc { |cc| cc }
54
+ cont, error = callcc { |cc| cc }
56
55
  if cont
57
- Thread.current.set_trace_func(tracer)
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.2
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-15 00:00:00.000000000 +02:00
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: &2153397620 !ruby/object:Gem::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: *2153397620
36
+ version_requirements: *2154182020
26
37
  - !ruby/object:Gem::Dependency
27
38
  name: bundler
28
- requirement: &2153396300 !ruby/object:Gem::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: *2153396300
47
+ version_requirements: *2154181540
37
48
  - !ruby/object:Gem::Dependency
38
49
  name: jeweler
39
- requirement: &2153395040 !ruby/object:Gem::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: *2153395040
58
+ version_requirements: *2154181060
48
59
  - !ruby/object:Gem::Dependency
49
60
  name: rcov
50
- requirement: &2153393200 !ruby/object:Gem::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: *2153393200
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/binding_of_caller.rb
110
+ - lib/ext/boc.rb
98
111
  - test/helper.rb
99
112
  - test/test_ara.rb
100
113
  has_rdoc: true