Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.DS_Store
pkg
doc
*.gem
build
4 changes: 2 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ desc "Compile the extension"
task :compile => "pkg/classes" do |t|
ant.javac :srcdir => "src", :destdir => t.prerequisites.first,
:source => "1.5", :target => "1.5", :debug => true,
:classpath => "${java.class.path}:${sun.boot.class.path}:lib/clojure-1.2.0.jar"
:classpath => "${java.class.path}:${sun.boot.class.path}:javalib/clojure-1.2.0.jar"
end

desc "Build the jar"
task :jar => :compile do
ant.jar :basedir => "pkg/classes", :destfile => "javalib/cloby_ext.jar", :includes => "**/*.class"
ant.jar :basedir => "pkg/classes", :destfile => "lib/cloby_ext.jar", :includes => "**/*.class"
end

task :package => :jar
Expand Down
13 changes: 13 additions & 0 deletions examples/agents.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require 'cloby'

ag = Agent.new 42

puts ag.deref # => 42

ag.dispatch 19 do |a,b|
a-b
end

puts ag.deref # => 23

Agent.shutdown # IMPORTANT! program will not exit if agents are not shutdown
18 changes: 18 additions & 0 deletions examples/atoms.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
require 'cloby'

atom = Atom.new 5

atom.swap{|a| a + 6}
puts atom.deref # => 11

puts atom.compare_and_set(42, 11) # => false
puts atom.deref # => 11

puts atom.compare_and_set(11, 42) # => true
puts atom.deref # => 42

puts atom.swap(1,2,3) {|a,b,c,d| a+b+c+d} # => 48

atom.reset 13

puts atom.deref # => 13
Binary file modified lib/cloby_ext.jar
Binary file not shown.
108 changes: 108 additions & 0 deletions src/org/jruby/clojure/ClojureAgent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package org.jruby.clojure;


import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyClass;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import clojure.lang.Agent;
import clojure.lang.ArraySeq;
import org.jruby.javasupport.JavaUtil;
import org.jruby.runtime.Block;
import org.jruby.RubyBoolean;
import static org.jruby.runtime.Visibility.*;

@JRubyClass(name = "Agent")
public class ClojureAgent extends RubyObject {

public static RubyClass createAgentClass(Ruby runtime) {
RubyClass agentc = runtime.defineClass("Agent", runtime.getObject(), AGENT_ALLOCATOR);
agentc.setReifiedClass(ClojureAgent.class);
agentc.kindOf = new RubyModule.KindOf() {
@Override
public boolean isKindOf(IRubyObject obj, RubyModule type) {
return obj instanceof ClojureAgent;
}
};
agentc.defineAnnotatedMethods(ClojureAgent.class);
return agentc;
}

private static ObjectAllocator AGENT_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new ClojureAgent(runtime, klass);
}
};

Ruby ruby;
Agent agent;

ClojureAgent(Ruby runtime, RubyClass klass) {
super(runtime, klass);
ruby = null;
agent = null;
}

@JRubyMethod(name = "shutdown", meta = true)
public static IRubyObject shutdown(ThreadContext context, IRubyObject recv) {
Agent.shutdown();
return context.getRuntime().getNil();
}

@JRubyMethod(visibility = PRIVATE)
public IRubyObject initialize(final ThreadContext context, final IRubyObject state, Block block) {
ruby = context.getRuntime();
try {
agent = new Agent(state);
this.setErrorHandler(context, block);
} catch (Exception e) {
throw ruby.newConcurrencyError(e.getLocalizedMessage());
}
return this;
}

@JRubyMethod(name = "dispatch", rest = true)
public IRubyObject dispatch(final ThreadContext context, final IRubyObject[] args, final Block block) {
agent.dispatch( new ClojureFunction(context, block), ArraySeq.create((Object[])args), true);
return ruby.getNil();
}

@JRubyMethod
public Object deref(final ThreadContext context) {
try {
return agent.deref();
} catch (Exception e) {
throw context.getRuntime().newConcurrencyError(e.getLocalizedMessage());
}
}

@JRubyMethod(name = "get_error")
public Object getError(final ThreadContext context) {
return agent.getError();
}

@JRubyMethod
public Object restart(final ThreadContext context, final IRubyObject newState) {
return restart(context, newState, context.getRuntime().getTrue());
}

@JRubyMethod
public Object restart(final ThreadContext context, final IRubyObject newState, final IRubyObject clearActions) {
try {
return agent.restart(newState, clearActions.isTrue());
} catch (Exception e) {
throw context.getRuntime().newConcurrencyError(e.getLocalizedMessage());
}
}

@JRubyMethod(name = "set_error_handler")
public IRubyObject setErrorHandler(final ThreadContext context, final Block block) {
agent.setErrorHandler(new ClojureFunction(context, block));
return context.getRuntime().getNil();
}
}
115 changes: 115 additions & 0 deletions src/org/jruby/clojure/ClojureAtom.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.jruby.clojure;

import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyClass;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.Block;
import clojure.lang.Atom;
import clojure.lang.ArraySeq;
import static org.jruby.runtime.Visibility.*;

@JRubyClass(name = "Atom")
public class ClojureAtom extends RubyObject {

public static RubyClass createAtomClass(final Ruby runtime) {
RubyClass atomc = runtime.defineClass("Atom", runtime.getObject(), ATOM_ALLOCATOR);
atomc.setReifiedClass(ClojureAtom.class);
atomc.kindOf = new RubyModule.KindOf() {
@Override
public boolean isKindOf(IRubyObject obj, RubyModule type) {
return obj instanceof ClojureAtom;
}
};
atomc.defineAnnotatedMethods(ClojureAtom.class);
return atomc;
}

Atom atom;

private static ObjectAllocator ATOM_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(final Ruby runtime, final RubyClass klass) {
return new ClojureAtom(runtime, klass);
}
};

public ClojureAtom(final Ruby runtime, final RubyClass klass) {
super(runtime, klass);
atom = null;
}

@JRubyMethod(visibility = PRIVATE)
public IRubyObject initialize(final ThreadContext context, final IRubyObject state) {
try {
atom = new Atom(state);
} catch (Exception e) {
throw context.getRuntime().newConcurrencyError(e.getLocalizedMessage());
}
return this;
}

@JRubyMethod
public Object swap(final ThreadContext context, final Block block) {
try {
return atom.swap(new ClojureFunction(context, block));
} catch (Exception e) {
throw context.getRuntime().newConcurrencyError(e.getLocalizedMessage());
}
}

@JRubyMethod
public Object swap(final ThreadContext context, final IRubyObject arg0, final Block block) {
try {
return atom.swap(new ClojureFunction(context, block), arg0);
} catch (Exception e) {
throw context.getRuntime().newConcurrencyError(e.getLocalizedMessage());
}
}

@JRubyMethod
public Object swap(final ThreadContext context, final IRubyObject arg0, final IRubyObject arg1, final Block block) {
try {
return atom.swap(new ClojureFunction(context, block), arg0, arg1);
} catch (Exception e) {
throw context.getRuntime().newConcurrencyError(e.getLocalizedMessage());
}
}

@JRubyMethod(rest = true)
public Object swap(final ThreadContext context, final IRubyObject[] args, final Block block) {
ArraySeq seq = ArraySeq.create((Object[])args);
Object arg0 = seq.get(0);
Object arg1 = seq.get(1);

try {
return atom.swap(new ClojureFunction(context, block), arg0, arg1, seq.next().next());
} catch (Exception e) {
throw context.getRuntime().newConcurrencyError(e.getLocalizedMessage());
}
}

@JRubyMethod(name = "compare_and_set")
public IRubyObject compareAndSet(ThreadContext context, IRubyObject oldv, IRubyObject newv){
return atom.compareAndSet(oldv, newv) ? context.getRuntime().getTrue() : context.getRuntime().getFalse();
}

@JRubyMethod
public Object reset(final ThreadContext context, final IRubyObject newVal) {
return atom.reset(newVal);
}

@JRubyMethod
public Object deref(final ThreadContext context) {
try {
return atom.deref();
} catch (Exception e) {
throw context.getRuntime().newConcurrencyError(e.getLocalizedMessage());
}
}

}
Loading