ara 0.0.2 → 0.0.3

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.
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