Skip to content

Commit ac116df

Browse files
committed
Make _1() method of memoized P1s smaller
so that the fast path can be inlined by the jvm. Also replaced Option by P1 in implementation, also avoid wrapping some more memoized instances.
1 parent 3ceef52 commit ac116df

File tree

1 file changed

+45
-39
lines changed

1 file changed

+45
-39
lines changed

core/src/main/java/fj/P1.java

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
package fj;
22

3-
import java.lang.ref.Reference;
4-
import java.lang.ref.SoftReference;
5-
import java.lang.ref.WeakReference;
6-
73
import fj.data.Array;
8-
import fj.data.List;
9-
import fj.data.Stream;
104
import fj.data.Either;
5+
import fj.data.List;
116
import fj.data.Option;
7+
import fj.data.Stream;
128
import fj.data.Validation;
9+
10+
import java.lang.ref.Reference;
11+
import java.lang.ref.SoftReference;
12+
import java.lang.ref.WeakReference;
13+
14+
import static fj.P.p;
1315
//import fj.data.*;
1416

1517

@@ -138,7 +140,7 @@ public final <B, C> P1<C> liftM2(P1<B> pb, F2<A, B, C> f) {
138140
* @return A single P1 for the given List.
139141
*/
140142
public static <A> P1<List<A>> sequence(final List<P1<A>> as) {
141-
return as.foldRight(liftM2(List.cons()), P.p(List.nil()));
143+
return as.foldRight(liftM2(List.cons()), p(List.nil()));
142144
}
143145

144146
/**
@@ -157,7 +159,7 @@ public static <A> F<List<P1<A>>, P1<List<A>>> sequenceList() {
157159
* @return A single P1 for the given stream.
158160
*/
159161
public static <A> P1<Stream<A>> sequence(final Stream<P1<A>> as) {
160-
return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil()));
162+
return as.foldRight(liftM2(Stream.cons()), p(Stream.nil()));
161163
}
162164

163165
/**
@@ -238,7 +240,7 @@ public final <B> P1<B> map(final F<A, B> f) {
238240
return P.lazy(() -> f.f(self._1()));
239241
}
240242

241-
public P1<A> memo() {
243+
public final P1<A> memo() {
242244
return weakMemo();
243245
}
244246

@@ -247,7 +249,7 @@ public P1<A> memo() {
247249
*
248250
* @return A P1 that calls this P1 once and remembers the value for subsequent calls.
249251
*/
250-
public final P1<A> hardMemo() { return new Memo<>(this); }
252+
public P1<A> hardMemo() { return new Memo<>(this); }
251253

252254
/**
253255
* Like <code>memo</code>, but the memoized value is wrapped into a <code>WeakReference</code>
@@ -267,65 +269,69 @@ public static <A> P1<A> memo(F0<A> f) {
267269
return P.lazy(f).memo();
268270
}
269271

270-
static class Memo<A> extends P1<A> {
272+
static final class Memo<A> extends P1<A> {
271273
private volatile P1<A> self;
272274
private A value;
273275

274276
Memo(P1<A> self) { this.self = self; }
275277

276278
@Override public final A _1() {
279+
return (self == null) ? value : computeValue();
280+
}
281+
282+
private synchronized A computeValue() {
283+
P1<A> self = this.self;
277284
if (self != null) {
278-
synchronized (this) {
279-
if (self != null) {
280-
A a = self._1();
281-
value = a;
282-
self = null;
283-
return a;
284-
}
285-
}
285+
value = self._1();
286+
this.self = null;
286287
}
287288
return value;
288289
}
289290

290-
@Override public final P1<A> memo() { return this; }
291+
@Override public P1<A> hardMemo() { return this; }
292+
@Override public P1<A> softMemo() { return this; }
293+
@Override public P1<A> weakMemo() { return this; }
291294
}
292295

293296
abstract static class ReferenceMemo<A> extends P1<A> {
294297
private final P1<A> self;
295-
private final Object latch = new Object();
296-
private volatile Reference<Option<A>> v = null;
298+
private volatile Reference<P1<A>> v = null;
297299

298300
ReferenceMemo(final P1<A> self) { this.self = self; }
299301

300302
@Override public final A _1() {
301-
Option<A> o = v != null ? v.get() : null;
302-
if (o == null) {
303-
synchronized (latch) {
304-
o = v != null ? v.get() : null;
305-
if (o == null) {
306-
o = Option.some(self._1());
307-
v = newReference(o);
308-
}
309-
}
303+
Reference<P1<A>> v = this.v;
304+
P1<A> p1 = v != null ? v.get() : null;
305+
return p1 != null ? p1._1() : computeValue();
306+
}
307+
308+
private synchronized A computeValue() {
309+
Reference<P1<A>> v = this.v;
310+
P1<A> p1 = v != null ? v.get() : null;
311+
if (p1 == null) {
312+
A a = self._1();
313+
this.v = newReference(p(a));
314+
return a;
310315
}
311-
return o.some();
316+
return p1._1();
312317
}
313318

314-
abstract Reference<Option<A>> newReference(Option<A> o);
319+
abstract <B> Reference<B> newReference(B ref);
315320
}
316321

317-
static class WeakReferenceMemo<A> extends ReferenceMemo<A> {
322+
static final class WeakReferenceMemo<A> extends ReferenceMemo<A> {
318323
WeakReferenceMemo(P1<A> self) { super(self); }
319324
@Override
320-
final Reference<Option<A>> newReference(final Option<A> o) { return new WeakReference<>(o); }
321-
@Override public final P1<A> weakMemo() { return this; }
325+
<B> Reference<B> newReference(final B ref) { return new WeakReference<>(ref); }
326+
@Override public P1<A> weakMemo() { return this; }
322327
}
323328

324-
static class SoftReferenceMemo<A> extends ReferenceMemo<A> {
329+
static final class SoftReferenceMemo<A> extends ReferenceMemo<A> {
325330
SoftReferenceMemo(P1<A> self) { super(self); }
326331
@Override
327-
final Reference<Option<A>> newReference(final Option<A> o) { return new SoftReference<>(o); }
328-
@Override public final P1<A> softMemo() { return this; }
332+
<B> Reference<B> newReference(final B ref) { return new SoftReference<>(ref); }
333+
@Override public P1<A> softMemo() { return this; }
334+
@Override public P1<A> weakMemo() { return this; }
329335
}
330336

331337
/**

0 commit comments

Comments
 (0)