public
Last active — forked from headius/1. cloby.rb

  • Download Gist
1. cloby.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
require 'clojure'
 
class MyClojureObj < Clojure::Object
def initialize
dosync { @foo = 'foo' }
end
 
def foo; @foo; end
def foo=(f); @foo = f; end
end
 
obj = MyClojureObj.new
puts "obj.foo = " + obj.foo
 
begin
puts "Setting obj.foo to 'bar'"
obj.foo = 'bar'
rescue ConcurrencyError
puts "Oops, need a transaction"
end
 
puts "Trying again with a transaction"
dosync { obj.foo = 'bar' }
puts "Success"
 
puts "obj.foo = " + obj.foo
2. output
1 2 3 4 5 6 7
~/projects/jruby ➔ jruby -J-Xbootclasspath/a:build_lib/clojure-1.0.0.jar cloby.rb
obj.foo = foo
Setting obj.foo to 'bar'
Oops, need a transaction
Trying again with a transaction
Success
obj.foo = bar
3. ClojureLibrary.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
package org.jruby.clojure;
 
import clojure.lang.IPersistentVector;
import clojure.lang.LockingTransaction;
import clojure.lang.PersistentVector;
import clojure.lang.Ref;
import java.io.IOException;
import java.util.concurrent.Callable;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;
 
public class ClojureLibrary implements Library{
public void load(Ruby runtime, boolean wrap) throws IOException {
RubyModule cljModule = runtime.defineModule("Clojure");
runtime.defineClassUnder("Object", runtime.getObject(), new ClojureObjectAllocator(), cljModule);
 
runtime.getKernel().defineAnnotatedMethods(ClojureDosync.class);
}
 
public static class ClojureObjectAllocator implements ObjectAllocator {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new ClojureObject(runtime, klazz);
}
}
 
public static class ClojureObject extends RubyObject {
public ClojureObject(Ruby runtime, RubyClass klass) {
super(runtime, klass);
try {
variableTable = new Ref(PersistentVector.EMPTY);
} catch (Exception e) {
throw runtime.newConcurrencyError(e.getLocalizedMessage());
}
}
 
@Override
public Object getVariable(int index) {
return ((IPersistentVector)variableTable.deref()).nth(index);
}
 
@Override
public void setVariable(int index, Object value) {
try {
variableTable.set(((IPersistentVector)variableTable.deref()).assocN(index, value));
} catch (IllegalStateException ise) {
throw getRuntime().newConcurrencyError(ise.getLocalizedMessage());
}
}
 
private final Ref variableTable;
}
 
public static class ClojureDosync {
@JRubyMethod
public static IRubyObject dosync(final ThreadContext context, final IRubyObject self, final Block block) {
final Ruby ruby = context.getRuntime();
try {
return (IRubyObject)LockingTransaction.runInTransaction(new Callable() {
public Object call() throws Exception {
// re-get transaction in case this gets run in different threads
return block.call(ruby.getCurrentContext());
}
});
} catch (Exception e) {
throw ruby.newConcurrencyError(e.getLocalizedMessage());
}
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.