Skip to content

Instantly share code, notes, and snippets.

@daveray
Created February 18, 2012 03:11
Show Gist options
  • Save daveray/1857150 to your computer and use it in GitHub Desktop.
Save daveray/1857150 to your computer and use it in GitHub Desktop.
Working JRuby/Clojure dosync
// Hacked from headius' version here: https://github.com/headius/clojr/blob/master/src/main/java/com/headius/clojr/ClojrLibrary.java
// See also https://jira.codehaus.org/browse/JRUBY-6149
public static IRubyObject dosync(final ThreadContext context, final IRubyObject self, final Block block) throws Exception {
final Ruby ruby = context.runtime;
return (IRubyObject) LockingTransaction.runInTransaction(new Callable() {
public Object call() throws Exception {
// re-get transaction in case this gets run in different threads
try {
final IRubyObject result = block.call(ruby.getCurrentContext());
return result;
} catch (RaiseException e) {
final RubyException rubyException = e.getException();
if(rubyException instanceof NativeException) {
// Peek in the native exception for RetryEx and retrow it raw.
// Otherwise retries won't work. The class name check is pretty
// kludgy, but RetryEx is package private :(
final NativeException ne = (NativeException) rubyException;
final Throwable cause = (Throwable) ne.getCause();
if(cause != null &&
"clojure.lang.LockingTransaction$RetryEx".equals(cause.getClass().getName())) {
throw (Error) cause;
}
else {
throw e;
}
}
else {
throw e;
}
}
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment