Skip to content

Commit 04863fd

Browse files
committed
Merge pull request #180 from ruby-concurrency/actress
Actors - Improving documentation; other improvements
2 parents d82334d + 0cead11 commit 04863fd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1156
-636
lines changed

doc/actor/celluloid_benchmark.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
require 'benchmark'
22
require 'concurrent/actor'
3-
Concurrent::Actor.i_know_it_is_experimental!
43

54
require 'celluloid'
65
require 'celluloid/autostart'

doc/actor/define.in.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Message = Struct.new :action, :value #
2+
3+
class AnActor < Concurrent::Actor::RestartingContext
4+
def initialize(init)
5+
@counter = init
6+
end
7+
8+
# override #on_message to define actor's behaviour on message received
9+
def on_message(message)
10+
case message.action
11+
when :add
12+
@counter = @counter + message.value
13+
when :subtract
14+
@counter = @counter - message.value
15+
when :value
16+
@counter
17+
else
18+
pass
19+
end
20+
end
21+
22+
# set counter to zero when there is an error
23+
def on_event(event)
24+
if event == :reset
25+
@counter = 0 # ignore initial value
26+
end
27+
end
28+
end #
29+
30+
an_actor = AnActor.spawn name: 'an_actor', args: 10 #
31+
an_actor << Message.new(:add, 1) << Message.new(:subtract, 2) #
32+
an_actor.ask!(Message.new(:value, nil))
33+
an_actor << :boo << Message.new(:add, 1) #
34+
an_actor.ask!(Message.new(:value, nil))
35+
an_actor << :terminate!
36+

doc/actor/define.out.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
Message = Struct.new :action, :value
2+
3+
class AnActor < Concurrent::Actor::RestartingContext
4+
def initialize(init)
5+
@counter = init
6+
end
7+
8+
# override #on_message to define actor's behaviour on message received
9+
def on_message(message)
10+
case message.action
11+
when :add
12+
@counter = @counter + message.value
13+
when :subtract
14+
@counter = @counter - message.value
15+
when :value
16+
@counter
17+
else
18+
pass
19+
end
20+
end
21+
22+
# set counter to zero when there is an error
23+
def on_event(event)
24+
if event == :reset
25+
@counter = 0 # ignore initial value
26+
end
27+
end
28+
end
29+
30+
an_actor = AnActor.spawn name: 'an_actor', args: 10
31+
an_actor << Message.new(:add, 1) << Message.new(:subtract, 2)
32+
an_actor.ask!(Message.new(:value, nil)) # => 9
33+
an_actor << :boo << Message.new(:add, 1)
34+
an_actor.ask!(Message.new(:value, nil)) # => 1
35+
an_actor << :terminate!
36+
# => #<Concurrent::Actor::Reference:0x7fb6fc9165d0 /an_actor (AnActor)>
37+

doc/actor/format.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@
33
require 'pry'
44
require 'pp'
55

6+
root = File.dirname(File.expand_path(Process.argv0))
67
input_paths = if ARGV.empty?
7-
Dir.glob("#{File.dirname(__FILE__)}/*.in.rb")
8+
Dir.glob("#{root}/*.in.rb")
89
else
910
ARGV
1011
end.map { |p| File.expand_path p }
1112

1213
input_paths.each_with_index do |input_path, i|
1314

1415
pid = fork do
15-
require_relative 'init.rb'
16+
require File.join(root, 'init.rb')
1617

1718
begin
1819
output_path = input_path.gsub /\.in\.rb$/, '.out.rb'

doc/actor/init.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
require 'concurrent/actor'
2-
Concurrent::Actor.i_know_it_is_experimental!
1+
require 'concurrent'
2+
require 'concurrent-edge'

doc/actor/io.in.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
require 'concurrent'
2+
3+
# logger = Logger.new(STDOUT)
4+
# Concurrent.configuration.logger = logger.method(:add)
5+
6+
# First option is to use operation pool
7+
8+
class ActorDoingIO < Concurrent::Actor::RestartingContext
9+
def on_message(message)
10+
# do IO operation
11+
end
12+
13+
def default_executor
14+
Concurrent.configuration.global_operation_pool
15+
end
16+
end #
17+
18+
actor_doing_io = ActorDoingIO.spawn :actor_doing_io
19+
actor_doing_io.executor == Concurrent.configuration.global_operation_pool
20+
21+
# It can be also built into a pool so there is not too many IO operations
22+
23+
class IOWorker < Concurrent::Actor::Utils::AbstractWorker
24+
def work(io_job)
25+
# do IO work
26+
sleep 0.1
27+
puts "#{path} second:#{(Time.now.to_f*100).floor} message:#{io_job}"
28+
end
29+
30+
def default_executor
31+
Concurrent.configuration.global_operation_pool
32+
end
33+
end #
34+
35+
pool = Concurrent::Actor::Utils::Pool.spawn('pool', 2) do |balancer, index|
36+
IOWorker.spawn(name: "worker-#{index}", args: [balancer])
37+
end
38+
39+
pool << 1 << 2 << 3 << 4 << 5 << 6
40+
41+
# prints two lines each second
42+
# /pool/worker-0 second:1414677666 message:1
43+
# /pool/worker-1 second:1414677666 message:2
44+
# /pool/worker-0 second:1414677667 message:3
45+
# /pool/worker-1 second:1414677667 message:4
46+
# /pool/worker-0 second:1414677668 message:5
47+
# /pool/worker-1 second:1414677668 message:6
48+
49+
sleep 1

doc/actor/io.out.rb

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
require 'concurrent' # => false
2+
3+
# logger = Logger.new(STDOUT)
4+
# Concurrent.configuration.logger = logger.method(:add)
5+
6+
# First option is to use operation pool
7+
8+
class ActorDoingIO < Concurrent::Actor::RestartingContext
9+
def on_message(message)
10+
# do IO operation
11+
end
12+
13+
def default_executor
14+
Concurrent.configuration.global_operation_pool
15+
end
16+
end
17+
18+
actor_doing_io = ActorDoingIO.spawn :actor_doing_io
19+
# => #<Concurrent::Actor::Reference:0x7fb6fc906068 /actor_doing_io (ActorDoingIO)>
20+
actor_doing_io.executor == Concurrent.configuration.global_operation_pool
21+
# => true
22+
23+
# It can be also built into a pool so there is not too many IO operations
24+
25+
class IOWorker < Concurrent::Actor::Utils::AbstractWorker
26+
def work(io_job)
27+
# do IO work
28+
sleep 0.1
29+
puts "#{path} second:#{(Time.now.to_f*100).floor} message:#{io_job}"
30+
end
31+
32+
def default_executor
33+
Concurrent.configuration.global_operation_pool
34+
end
35+
end
36+
37+
pool = Concurrent::Actor::Utils::Pool.spawn('pool', 2) do |balancer, index|
38+
IOWorker.spawn(name: "worker-#{index}", args: [balancer])
39+
end
40+
# => #<Concurrent::Actor::Reference:0x7fb6fc964190 /pool (Concurrent::Actor::Utils::Pool)>
41+
42+
pool << 1 << 2 << 3 << 4 << 5 << 6
43+
# => #<Concurrent::Actor::Reference:0x7fb6fc964190 /pool (Concurrent::Actor::Utils::Pool)>
44+
45+
# prints two lines each second
46+
# /pool/worker-0 second:1414677666 message:1
47+
# /pool/worker-1 second:1414677666 message:2
48+
# /pool/worker-0 second:1414677667 message:3
49+
# /pool/worker-1 second:1414677667 message:4
50+
# /pool/worker-0 second:1414677668 message:5
51+
# /pool/worker-1 second:1414677668 message:6
52+
53+
sleep 1 # => 1

0 commit comments

Comments
 (0)