Skip to content
Merged
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
4 changes: 3 additions & 1 deletion ext/ConcurrentRubyExtService.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import java.io.IOException;

import org.jruby.Ruby;
import org.jruby.runtime.load.BasicLibraryService;

public class ConcurrentRubyExtService implements BasicLibraryService {
public boolean basicLoad(final Ruby runtime) throws IOException {
new com.concurrent_ruby.ext.AtomicReferenceLibrary().load(runtime, false);
new com.concurrent_ruby.ext.JavaAtomicBooleanLibrary().load(runtime, false);
new com.concurrent_ruby.ext.JavaAtomicFixnumLibrary().load(runtime, false);
return true;
}
}
96 changes: 96 additions & 0 deletions ext/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.concurrent_ruby.ext;

import java.io.IOException;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jruby.RubyBoolean;
import org.jruby.RubyNil;
import org.jruby.runtime.ThreadContext;

public class JavaAtomicBooleanLibrary implements Library {

public void load(Ruby runtime, boolean wrap) throws IOException {
RubyModule concurrentMod = runtime.defineModule("Concurrent");
RubyClass atomicCls = concurrentMod.defineClassUnder("JavaAtomicBoolean", runtime.getObject(), JRUBYREFERENCE_ALLOCATOR);
atomicCls.defineAnnotatedMethods(JavaAtomicBoolean.class);
}

private static final ObjectAllocator JRUBYREFERENCE_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JavaAtomicBoolean(runtime, klazz);
}
};

@JRubyClass(name = "JavaAtomicBoolean", parent = "Object")
public static class JavaAtomicBoolean extends RubyObject {

private AtomicBoolean atomicBoolean;
private ThreadContext context;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I've missed this on first time. I believe this should not be stored in the object's field. The ThreadContext can change on each method call, it should be always first argument of the @JRubyMethods.


public JavaAtomicBoolean(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}

@JRubyMethod
public IRubyObject initialize(ThreadContext context, IRubyObject value) {
atomicBoolean = new AtomicBoolean(convertRubyBooleanToJavaBoolean(value));
this.context = context;
return context.nil;
}

@JRubyMethod
public IRubyObject initialize(ThreadContext context) {
atomicBoolean = new AtomicBoolean();
this.context = context;
return context.nil;
}

@JRubyMethod(name = "value")
public IRubyObject value() {
return RubyBoolean.newBoolean(getRuntime(), atomicBoolean.get());
}

@JRubyMethod(name = "true?")
public IRubyObject isAtomicTrue() {
return RubyBoolean.newBoolean(getRuntime(), atomicBoolean.get());
}

@JRubyMethod(name = "false?")
public IRubyObject isAtomicFalse() {
return RubyBoolean.newBoolean(getRuntime(), (atomicBoolean.get() == false));
}

@JRubyMethod(name = "value=")
public IRubyObject setAtomic(IRubyObject newValue) {
atomicBoolean.set(convertRubyBooleanToJavaBoolean(newValue));
return context.nil;
}

@JRubyMethod(name = "make_true")
public IRubyObject makeTrue() {
return RubyBoolean.newBoolean(getRuntime(), atomicBoolean.compareAndSet(false, true));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could also be getRuntime().newBoolean(atomicBoolean.compareAndSet(false, true)).

}

@JRubyMethod(name = "make_false")
public IRubyObject makeFalse() {
return RubyBoolean.newBoolean(getRuntime(), atomicBoolean.compareAndSet(true, false));
}

private boolean convertRubyBooleanToJavaBoolean(IRubyObject newValue) {
if (newValue instanceof RubyBoolean.False || newValue instanceof RubyNil) {
return false;
} else {
return true;
}
}
}
}

94 changes: 94 additions & 0 deletions ext/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.concurrent_ruby.ext;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
import org.jruby.Ruby;
import org.jruby.RubyBoolean;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;

public class JavaAtomicFixnumLibrary implements Library {

public void load(Ruby runtime, boolean wrap) throws IOException {
RubyModule concurrentMod = runtime.defineModule("Concurrent");
RubyClass atomicCls = concurrentMod.defineClassUnder("JavaAtomicFixnum", runtime.getObject(), JRUBYREFERENCE_ALLOCATOR);

atomicCls.defineAnnotatedMethods(JavaAtomicFixnum.class);

}

private static final ObjectAllocator JRUBYREFERENCE_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JavaAtomicFixnum(runtime, klazz);
}
};

@JRubyClass(name = "JavaAtomicFixnum", parent = "Object")
public static class JavaAtomicFixnum extends RubyObject {

private AtomicLong atomicLong;
private ThreadContext context;

public JavaAtomicFixnum(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}

@JRubyMethod
public IRubyObject initialize(ThreadContext context) {
this.atomicLong = new AtomicLong(0);
this.context = context;
return context.nil;
}

@JRubyMethod
public IRubyObject initialize(ThreadContext context, IRubyObject value) {
this.atomicLong = new AtomicLong(rubyFixnumToLong(value));
this.context = context;
return context.nil;
}

@JRubyMethod(name = "value")
public IRubyObject getValue() {
return new RubyFixnum(getRuntime(), atomicLong.get());
}

@JRubyMethod(name = "value=")
public IRubyObject setValue(IRubyObject newValue) {
atomicLong.set(rubyFixnumToLong(newValue));
return context.nil;
}

@JRubyMethod(name = {"increment", "up"})
public IRubyObject increment() {
return new RubyFixnum(getRuntime(), atomicLong.incrementAndGet());
}

@JRubyMethod(name = {"decrement", "down"})
public IRubyObject decrement() {
return new RubyFixnum(getRuntime(), atomicLong.decrementAndGet());
}

@JRubyMethod(name = "compare_and_set")
public IRubyObject compareAndSet(IRubyObject expect, IRubyObject update) {
return RubyBoolean.newBoolean(getRuntime(), atomicLong.compareAndSet(rubyFixnumToLong(expect), rubyFixnumToLong(update)));
}

private long rubyFixnumToLong(IRubyObject value) {
if (value instanceof RubyFixnum) {
RubyFixnum fixNum = (RubyFixnum) value;
return fixNum.getLongValue();
} else {
throw getRuntime().newArgumentError("initial value must be a Fixnum");
}
}
}
}

43 changes: 0 additions & 43 deletions lib/concurrent/atomic/atomic_boolean.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,49 +115,6 @@ def make_false

if RUBY_PLATFORM == 'java'

# @!macro atomic_boolean
class JavaAtomicBoolean

# @!macro atomic_boolean_method_initialize
#
def initialize(initial = false)
@atomic = java.util.concurrent.atomic.AtomicBoolean.new(!!initial)
end

# @!macro atomic_boolean_method_value_get
#
def value
@atomic.get
end

# @!macro atomic_boolean_method_value_set
#
def value=(value)
@atomic.set(!!value)
end

# @!macro atomic_boolean_method_true_question
def true?
@atomic.get
end

# @!macro atomic_boolean_method_false_question
def false?
[email protected]
end

# @!macro atomic_boolean_method_make_true
def make_true
@atomic.compareAndSet(false, true)
end

# @!macro atomic_boolean_method_make_false
def make_false
@atomic.compareAndSet(true, false)
end
end

# @!macro atomic_boolean
class AtomicBoolean < JavaAtomicBoolean
end

Expand Down
45 changes: 2 additions & 43 deletions lib/concurrent/atomic/atomic_fixnum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,14 @@ def decrement
alias_method :down, :decrement

# @!macro [attach] atomic_fixnum_method_compare_and_set
#
#
# Atomically sets the value to the given updated value if the current
# value == the expected value.
#
# @param [Fixnum] expect the expected value
# @param [Fixnum] update the new value
#
# @return [Boolean] true if the value was updated else false
# @return [Boolean] true if the value was updated else false
def compare_and_set(expect, update)
@mutex.lock
if @value == expect
Expand All @@ -120,47 +120,6 @@ def compare_and_set(expect, update)

if RUBY_PLATFORM == 'java'

# @!macro atomic_fixnum
class JavaAtomicFixnum

MIN_VALUE = Java::JavaLang::Long::MIN_VALUE
MAX_VALUE = Java::JavaLang::Long::MAX_VALUE

# @!macro atomic_fixnum_method_initialize
def initialize(init = 0)
raise ArgumentError.new('initial value must be a Fixnum') unless init.is_a?(Fixnum)
@atomic = java.util.concurrent.atomic.AtomicLong.new(init)
end

# @!macro atomic_fixnum_method_value_get
def value
@atomic.get
end

# @!macro atomic_fixnum_method_value_set
def value=(value)
raise ArgumentError.new('value must be a Fixnum') unless value.is_a?(Fixnum)
@atomic.set(value)
end

# @!macro atomic_fixnum_method_increment
def increment
@atomic.increment_and_get
end
alias_method :up, :increment

# @!macro atomic_fixnum_method_decrement
def decrement
@atomic.decrement_and_get
end
alias_method :down, :decrement

# @!macro atomic_fixnum_method_compare_and_set
def compare_and_set(expect, update)
@atomic.compare_and_set(expect, update)
end
end

# @!macro atomic_fixnum
class AtomicFixnum < JavaAtomicFixnum
end
Expand Down