Skip to content

Instantly share code, notes, and snippets.

@seki
Created November 8, 2012 13:56
Show Gist options
  • Save seki/4038950 to your computer and use it in GitHub Desktop.
Save seki/4038950 to your computer and use it in GitHub Desktop.
Erlang like actor using Rinda
require 'rinda/tuplespace'
module Actor
class Channel
def initialize(ts, key)
@ts = ts
@pid = key
end
attr_reader :pid
def spawn(*args)
_, pid ,= @ts.take([:pid, nil])
pid += 1
@ts.write([:pid, pid])
Thread.new(Channel.new(@ts, pid), args) do |ch, args|
begin
Thread.current['channel'] = ch
catch(Actor) do
yield(*args)
end
rescue
send(@pid, :EXIT, ch.pid, $!)
ensure
send(@pid, :EXIT, ch.pid, :normal_exit)
end
end
pid
end
def send(to, *message)
@ts.write([to, *message])
end
def receive(*pattern)
if block_given?
timeout = pattern.pop
else
timeout = nil
end
_, *rest = @ts.take([@pid, *pattern], timeout)
rest
rescue Rinda::RequestExpiredError
yield
end
end
TS = Rinda::TupleSpace.new(1)
TS.write([:pid, 0])
Thread.current['channel'] = Channel.new(TS, 0)
module_function
def send(to, *message)
Thread.current['channel'].send(to, *message)
end
def receive(*pattern, &block)
Thread.current['channel'].receive(*pattern, &block)
end
def spawn(*args, &block)
Thread.current['channel'].spawn(*args, &block)
end
def pid
Thread.current['channel'].pid
end
end
if __FILE__ == $0
echo = Actor.spawn do
while true
str ,= Actor.receive(String, 2) do
p :timeout
throw(Actor)
end
p str
end
end
Actor.send(echo, 'hello')
Actor.send(echo, 'hello')
p Actor.receive(:EXIT, nil, nil)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment