Skip to content

Instantly share code, notes, and snippets.

@michaelfairley
Created November 24, 2012 18:01
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save michaelfairley/4140714 to your computer and use it in GitHub Desktop.
Save michaelfairley/4140714 to your computer and use it in GitHub Desktop.
jruby-go

jruby-go

Go's concurrency model on top of JRuby

Channels

Channel.new creates a channel, and you can optionally pass it a capacity: Channel.new(200)

Use << to send on a channel: chan << "stuff"

Use ~ to receive from a channel: puts ~chan

Goroutines

Call go! on a Proc or Method to start a new goroutine: lambda { puts "hello there" }.go!

You can pass arguments to go!: method(:puts).go!("greetings")

You can also call go! top level and pass it a block: go! { puts "make sure not to share mutable state through the closure's context" }

Issues

One thing I didn't solve for: selecting on multiple channels

require 'java'
GOROUTINE_EXECUTOR = java.util.concurrent.Executors.newCachedThreadPool
GOROUTINE_EXECUTOR.set_thread_factory(Class.new do
include java.util.concurrent.ThreadFactory
def newThread(r)
thread = java.util.concurrent.Executors.defaultThreadFactory.newThread(r)
thread.set_daemon(true)
thread
end
end.new)
class Channel
def initialize(capacity = 100)
@queue = java.util.concurrent.ArrayBlockingQueue.new(100)
end
def <<(message)
@queue.put(message)
end
def ~()
@queue.take
end
end
module Goable
def go!(*args)
GOROUTINE_EXECUTOR.submit(lambda{self.call(*args)})
end
end
Method.send(:include, Goable)
Proc.send(:include, Goable)
def go!(*args, &blk)
blk.go!(*args)
end
require 'jruby-go'
# jruby-go port of http://golang.org/doc/play/sieve.go
def generate(ch)
2.upto(1.0/0) do |i|
ch << i
end
end
def filter(inn, out, prime)
loop do
i = ~inn
if i % prime != 0
out << i
end
end
end
ch = Channel.new
method(:generate).go!(ch)
# This can also be `go! ch, &method(:generate)`
10.times do
prime = ~ch
puts prime
ch1 = Channel.new
method(:filter).go!(ch, ch1, prime)
ch = ch1
end
require 'jruby-go'
chan = Channel.new
# << sends on a channel
go! { puts "hello"; chan << "goodbye" }
# ~ receives from a channel
puts ~chan
# You can also call go! on a callable if you want to pass it args
lambda { |a, b| puts a; chan << b }.go!("hola", "adios")
puts ~chan
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment