-
Notifications
You must be signed in to change notification settings - Fork 420
[Improvement] - Initial implementation of Concurrent::AtomicBoolean in pure Java #236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
|
||
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)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could also be |
||
} | ||
|
||
@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; | ||
} | ||
} | ||
} | ||
} | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | ||
} | ||
} | ||
} | ||
} | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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@JRubyMethod
s.