Skip to content

Commit f8bb41a

Browse files
committed
Revert "Replaced internal CHM with Java version."
This reverts commit 36fd269. Conflicts: ext/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java
1 parent b9561b4 commit f8bb41a

File tree

11 files changed

+8970
-21
lines changed

11 files changed

+8970
-21
lines changed

ext/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
import org.jruby.*;
44
import org.jruby.anno.JRubyClass;
55
import org.jruby.anno.JRubyMethod;
6+
import com.concurrent_ruby.ext.jsr166e.ConcurrentHashMap;
7+
import com.concurrent_ruby.ext.jsr166e.ConcurrentHashMapV8;
8+
import com.concurrent_ruby.ext.jsr166e.nounsafe.*;
69
import org.jruby.runtime.Block;
710
import org.jruby.runtime.ObjectAllocator;
811
import org.jruby.runtime.ThreadContext;
912
import org.jruby.runtime.builtin.IRubyObject;
1013
import org.jruby.runtime.load.Library;
11-
import java.util.Iterator;
12-
import java.util.function.BiFunction;
13-
import java.util.function.Function;
14-
import java.util.concurrent.ConcurrentHashMap;
1514

1615
import java.io.IOException;
1716
import java.util.Map;
@@ -45,16 +44,35 @@ public static class JRubyMapBackend extends RubyObject {
4544
static final int DEFAULT_INITIAL_CAPACITY = 16;
4645
static final float DEFAULT_LOAD_FACTOR = 0.75f;
4746

47+
public static final boolean CAN_USE_UNSAFE_CHM = canUseUnsafeCHM();
48+
4849
private ConcurrentHashMap<IRubyObject, IRubyObject> map;
4950

5051
private static ConcurrentHashMap<IRubyObject, IRubyObject> newCHM(int initialCapacity, float loadFactor) {
51-
return new java.util.concurrent.ConcurrentHashMap<IRubyObject, IRubyObject>(initialCapacity, loadFactor);
52+
if (CAN_USE_UNSAFE_CHM) {
53+
return new ConcurrentHashMapV8<IRubyObject, IRubyObject>(initialCapacity, loadFactor);
54+
} else {
55+
return new com.concurrent_ruby.ext.jsr166e.nounsafe.ConcurrentHashMapV8<IRubyObject, IRubyObject>(initialCapacity, loadFactor);
56+
}
5257
}
5358

5459
private static ConcurrentHashMap<IRubyObject, IRubyObject> newCHM() {
5560
return newCHM(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
5661
}
5762

63+
private static boolean canUseUnsafeCHM() {
64+
try {
65+
new com.concurrent_ruby.ext.jsr166e.ConcurrentHashMapV8(); // force class load and initialization
66+
return true;
67+
} catch (Throwable t) { // ensuring we really do catch everything
68+
// Doug's Unsafe setup errors always have this "Could not ini.." message
69+
if (isCausedBySecurityException(t)) {
70+
return false;
71+
}
72+
throw (t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t));
73+
}
74+
}
75+
5876
private static boolean isCausedBySecurityException(Throwable t) {
5977
while (t != null) {
6078
if ((t.getMessage() != null && t.getMessage().contains("Could not initialize intrinsics")) || t instanceof SecurityException) {
@@ -114,7 +132,7 @@ public IRubyObject put_if_absent(IRubyObject key, IRubyObject value) {
114132

115133
@JRubyMethod
116134
public IRubyObject compute_if_absent(final ThreadContext context, final IRubyObject key, final Block block) {
117-
return map.computeIfAbsent(key, new java.util.function.Function<IRubyObject, IRubyObject>() {
135+
return map.computeIfAbsent(key, new ConcurrentHashMap.Fun<IRubyObject, IRubyObject>() {
118136
@Override
119137
public IRubyObject apply(IRubyObject key) {
120138
return block.yieldSpecific(context);
@@ -124,7 +142,7 @@ public IRubyObject apply(IRubyObject key) {
124142

125143
@JRubyMethod
126144
public IRubyObject compute_if_present(final ThreadContext context, final IRubyObject key, final Block block) {
127-
IRubyObject result = map.computeIfPresent(key, new java.util.function.BiFunction<IRubyObject, IRubyObject, IRubyObject>() {
145+
IRubyObject result = map.computeIfPresent(key, new ConcurrentHashMap.BiFun<IRubyObject, IRubyObject, IRubyObject>() {
128146
@Override
129147
public IRubyObject apply(IRubyObject key, IRubyObject oldValue) {
130148
IRubyObject result = block.yieldSpecific(context, oldValue == null ? context.getRuntime().getNil() : oldValue);
@@ -136,7 +154,7 @@ public IRubyObject apply(IRubyObject key, IRubyObject oldValue) {
136154

137155
@JRubyMethod
138156
public IRubyObject compute(final ThreadContext context, final IRubyObject key, final Block block) {
139-
IRubyObject result = map.compute(key, new java.util.function.BiFunction<IRubyObject, IRubyObject, IRubyObject>() {
157+
IRubyObject result = map.compute(key, new ConcurrentHashMap.BiFun<IRubyObject, IRubyObject, IRubyObject>() {
140158
@Override
141159
public IRubyObject apply(IRubyObject key, IRubyObject oldValue) {
142160
IRubyObject result = block.yieldSpecific(context, oldValue == null ? context.getRuntime().getNil() : oldValue);
@@ -148,7 +166,7 @@ public IRubyObject apply(IRubyObject key, IRubyObject oldValue) {
148166

149167
@JRubyMethod
150168
public IRubyObject merge_pair(final ThreadContext context, final IRubyObject key, final IRubyObject value, final Block block) {
151-
IRubyObject result = map.merge(key, value, new java.util.function.BiFunction<IRubyObject, IRubyObject, IRubyObject>() {
169+
IRubyObject result = map.merge(key, value, new ConcurrentHashMap.BiFun<IRubyObject, IRubyObject, IRubyObject>() {
152170
@Override
153171
public IRubyObject apply(IRubyObject oldValue, IRubyObject newValue) {
154172
IRubyObject result = block.yieldSpecific(context, oldValue == null ? context.getRuntime().getNil() : oldValue);
@@ -164,20 +182,14 @@ public RubyBoolean replace_pair(IRubyObject key, IRubyObject oldValue, IRubyObje
164182
}
165183

166184
@JRubyMethod(name = "key?", required = 1)
167-
public RubyBoolean has_key_p(IRubyObject key) {
168-
return map.containsKey(key) ? getRuntime().getTrue() : getRuntime().getFalse();
169-
}
185+
public RubyBoolean has_key_p(IRubyObject key) {
186+
return map.containsKey(key) ? getRuntime().getTrue() : getRuntime().getFalse();
187+
}
170188

171189
@JRubyMethod
172190
public IRubyObject key(IRubyObject value) {
173-
Iterator itr = map.entrySet().iterator();
174-
while(itr.hasNext()) {
175-
Map.Entry<IRubyObject, IRubyObject> entry = (Map.Entry<IRubyObject, IRubyObject>) itr.next();
176-
if (entry.getValue() == value) {
177-
return entry.getKey();
178-
}
179-
}
180-
return null;
191+
final IRubyObject key = map.findKey(value);
192+
return key == null ? getRuntime().getNil() : key;
181193
}
182194

183195
@JRubyMethod
@@ -224,7 +236,7 @@ public RubyFixnum size(ThreadContext context) {
224236

225237
@JRubyMethod
226238
public IRubyObject get_or_default(IRubyObject key, IRubyObject defaultValue) {
227-
return map.getOrDefault(key, defaultValue);
239+
return map.getValueOrDefault(key, defaultValue);
228240
}
229241

230242
@JRubyMethod(visibility = PRIVATE)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.concurrent_ruby.ext.jsr166e;
2+
3+
import java.util.Map;
4+
import java.util.Set;
5+
6+
public interface ConcurrentHashMap<K, V> {
7+
/** Interface describing a function of one argument */
8+
public interface Fun<A,T> { T apply(A a); }
9+
/** Interface describing a function of two arguments */
10+
public interface BiFun<A,B,T> { T apply(A a, B b); }
11+
12+
public V get(K key);
13+
public V put(K key, V value);
14+
public V putIfAbsent(K key, V value);
15+
public V computeIfAbsent(K key, Fun<? super K, ? extends V> mf);
16+
public V computeIfPresent(K key, BiFun<? super K, ? super V, ? extends V> mf);
17+
public V compute(K key, BiFun<? super K, ? super V, ? extends V> mf);
18+
public V merge(K key, V value, BiFun<? super V, ? super V, ? extends V> mf);
19+
public boolean replace(K key, V oldVal, V newVal);
20+
public V replace(K key, V value);
21+
public boolean containsKey(K key);
22+
public boolean remove(Object key, Object value);
23+
public V remove(K key);
24+
public void clear();
25+
public Set<Map.Entry<K,V>> entrySet();
26+
public int size();
27+
public V getValueOrDefault(Object key, V defaultValue);
28+
29+
public boolean containsValue(V value);
30+
public K findKey(V value);
31+
}

0 commit comments

Comments
 (0)