Fogcity Ruby meetup


Carbon Five 585 Howard St, 2nd Floor, San Francisco, CA

7:15pm - Containerized Ruby, Julian Fahrer
7:45pm — Concurrent Ruby Patterns, Gonzalo Maldonado

Containerized Ruby

Patching the ContainerOS?


Concurrent Ruby Patterns. How to Speed Up Your Code Using Async Methods, Futures, and Promises

exmaple with threads

threads = (1..3)map do |i|
  Thread.new(i) do |i|
    arr = instance_variable_get("@arr#{i}")
    puts "arr#{i} = #{ add(arr) }"
  end
end

threads.each {|t| t.join}

thread safety

@n = 0
3.times do 
  Thread.start { 100.times {@n += 1}}
end
# it will break
gem install concurrent-ruby

Async

class Echo
  include Concurrent::Async

  def echo(msg)
    print "#{msg}\n"
  end
end

horn = Echo.new
horn.echo('zero') # sync, not thread-safe
horn.async.echo('one') # async, non-blocking, thread-safe, return IVar in the :pending state
horn.await.echo('two') # sync, blocking, thread-safe, return IVar in the :complete state

Promises

p = Concurrent::Promise
      .fulfill(20)
      .then { |result| result - 10 }
      .then { |result} result * 3 }
      .then(eecutor: different_executor) { |result result % 5}.execute

How:

p = Concurrent::Promise.execute{ "hello, world! "}
sleep(0.1)

p.state # :fulfilled
p.fulfilled? # true
p.value 

p = Concurrent::Promise.execute { raise StandardError.new("Here comes the Boom!")}
sleep(0.1)

p.state # :rejected
p.rejected? # true
p.reason # <StandardError>

...

Channel

puts "Main thread: #{Thread.current"}"

Concurrent::Channel.go do
  puts 'Goroutin thread: #{Thread.current}'
end
c1 = Concurrent::Channel.new
c2 = Concurrent::Channel.new

Concurent::Channel.go do
  sleep(2)
  c2 << 'two'
end

Concurrent::Channel.go do
  sleep(1)
  c1 << 'one'
end

2.times do
  Concurrent::Channel.select do |s|
    s.take(c1) {|msg| print "received #{msg}\n"}
    s.take(c2) {|msg| print "received #{msg}\n"}
  end
end

Warnings