Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby acting up: A look at how Celluloid impleme...

Ruby acting up: A look at how Celluloid implements the actor model for concurrency in Ruby.

Arjan van der Gaag

November 11, 2015

Transcript

23 slides
  1. Ruby acting up A look at how Celluloid implements the

    actor
 model for concurrency in Ruby.
  2. Actor /ˈaktə/ noun 1. a participant in an action or

    process. 2. a process with an inbox for receiving messages.
  3. Queues require 'thread' @running = true @queue = Queue.new Thread.new

    do while @running do message = @queue.pop # do something interesting with message end end
  4. Actor object class Actor def initialize @running = true @queue

    = Queue.new @thread = Thread.new do while @running do process_message( @queue.pop ) end end end def stop @running = false end private def process_message(msg) # do stuff here end end
  5. Thread safety class Actor def initialize @counter = 0 end

    def process_message(msg) @counter += 1 end end
  6. Thread safety class Actor def initialize @counter = 0 end

    def process_message(msg) @counter = (@counter + 1) end end
  7. Queueing messages class Greeter def greet(name) puts "Hello, #{name}!" end

    end greeter = Greeter.new @queue << [:greet, "John"] greeter.send *@queue.pop
  8. Actor delegates to object class Actor def initialize(target) @target =

    target @thread = Thread.new do process_inbox end end def process_inbox while @running process_message *@queue.pop end end def process_message(func, *args) @mutex.synchronize do target.public_send(
 func, *args ) end end end
  9. Actor send_async class Actor def send_async(*args) @queue << args end

    end class Greeter def greet(name) puts "Hello, #{name}!" end end greeter = Greeter.new actor = Actor.new(greeter) actor.send_async( :greet, 'John' )
  10. Celluloid actor mixin module Celluloid def self.included(base) base.extend ClassMethods end

    module ClassMethods def new(*args) Actor.new(super) end end class Actor def method_missing(*args) target .public_send(*args) end end end
  11. Celluloid async proxy module Celluloid class Actor def initialize(target) @proxy

    = AsyncProxy.new(self) end def async @proxy end end class AsyncProxy def initialize(actor) @actor = actor end def method_missing(*args) @actor.send_async(*args) end end end
  12. Celluloid example class Pinger URL = "http://www.google.com/webmasters/tools/ping?sitemap=%s" include Celluloid def

    ping(sitemap_url) Net::HTTP.get(URL % sitemap_url) end end pinger = Pinger.new url = 'http://arjanvandergaag.nl/sitemap.xml' pinger.ping(url) # => wait... 200 OK" pinger.async.ping(url) # => nil
  13. Celluloid futures pinger.ping(url) # => "200 OK" future = pinger.future.ping(url)

    # => #<Celluloid::Future:0x000001009759b8> future.value # => "200 OK"
  14. Ruby promises with Whenner pinger.ping.then do |on| on.done do |value|

    puts "Done with status #{value}" end on.fail do |value| puts "Something bad happened!" end end Whenner.when(pinger.ping, ponger.pong).done do |results| results.each do |status| puts status end end
  15. Find out more • Celluloid • Celluloid::IO • Concurrent Programming

    with Celluloid (Tony Arcieri, MountainWest RubyConf 2012) • Sidekiq • RubyTapas • Whenner

More Decks by Arjan van der Gaag

Other Decks in Programming