Skip to content

Instantly share code, notes, and snippets.

@zhouguangming
Created August 16, 2013 03:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhouguangming/6246929 to your computer and use it in GitHub Desktop.
Save zhouguangming/6246929 to your computer and use it in GitHub Desktop.
actor in ruby
require 'thread'
module Actor
module ClassMethods
def new(*args, &block)
Proxy.new(super)
end
end
class << self
def included(klass)
klass.extend(ClassMethods)
end
def current
Thread.current[:actor]
end
end
class Proxy
def initialize(target)
@target = target
@mailbox = Queue.new
@mutex = Mutex.new
@running = true
@async_proxy = AsyncProxy.new(self)
@thread = Thread.new do
Thread.current[:actor] = self
process_inbox
end
end
def async
@async_proxy
end
def send_later(meth, *args)
@mailbox << [meth, args]
end
def terminate
@running = false
end
def method_missing(meth, *args)
process_message(meth, *args)
end
private
def process_inbox
while @running
meth, args = @mailbox.pop
process_message(meth, *args)
end
rescue Exception => ex
puts "Error while running actor: #{ex}"
end
def process_message(meth, *args)
@mutex.synchronize do
@target.public_send(meth, *args)
end
end
end
class AsyncProxy
def initialize(actor)
@actor = actor
end
def method_missing(meth, *args)
@actor.send_later(meth, *args)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment