Skip to content

Commit

Permalink
[#54] TCO reworked (now look-ahead is unnecessary); appendSum test;
Browse files Browse the repository at this point in the history
mayHaveCloseAction -> delegateClose
  • Loading branch information
amaembo committed Jan 17, 2016
1 parent 52b1396 commit b43e512
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 119 deletions.
5 changes: 1 addition & 4 deletions src/main/java/one/util/streamex/AbstractStreamEx.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,7 @@ StreamFactory strategy() {
}

final <R> Stream<R> delegate(Spliterator<R> spliterator) {
Stream<R> result = StreamSupport.stream(spliterator, stream.isParallel());
if(mayHaveCloseAction(stream))
result = result.onClose(stream::close);
return result;
return delegateClose(StreamSupport.stream(spliterator, stream.isParallel()), stream);
}

final S callWhile(Predicate<? super T> predicate, int methodId) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/one/util/streamex/DoubleStreamEx.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ StreamFactory strategy() {

final DoubleStreamEx delegate(Spliterator.OfDouble spliterator) {
return strategy().newDoubleStreamEx(
StreamSupport.doubleStream(spliterator, stream.isParallel()).onClose(stream::close));
delegateClose(StreamSupport.doubleStream(spliterator, stream.isParallel()), stream));
}

final DoubleStreamEx callWhile(DoublePredicate predicate, int methodId) {
Expand Down
68 changes: 27 additions & 41 deletions src/main/java/one/util/streamex/HeadTailSpliterator.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.stream.BaseStream;
import java.util.stream.Stream;

import one.util.streamex.StreamExInternals.TailCallSpliterator;
import static one.util.streamex.StreamExInternals.*;

/**
Expand All @@ -45,59 +46,53 @@
this.emptyMapper = emptyMapper;
}

private static <T> Spliterator<T> traverseTail(Spliterator<T> spltr) {
Spliterator<T> current = spltr;
while (current instanceof TailCallSpliterator) {
Spliterator<T> next = ((TailCallSpliterator<T>) current).tail();
if (next == current)
break;
current = next;
}
return current;
}

@Override
public boolean tryAdvance(Consumer<? super U> action) {
if(!init())
return false;
target = traverseTail(target);
return finishUnless(target.tryAdvance(action));
target = TailCallSpliterator.tryAdvanceWithTail(target, action);
if(target == null) {
finished = true;
return false;
}
return true;
}

@Override
public void forEachRemaining(Consumer<? super U> action) {
if(init()) {
Spliterator<U> t = target;
while(t instanceof TailCallSpliterator) {
t = traverseTail(t);
if(!finishUnless(t.tryAdvance(action)))
return;
}
t.forEachRemaining(action);
finishUnless(false);
}
public Spliterator<U> tryAdvanceOrTail(Consumer<? super U> action) {
if(!init())
return null;
Spliterator<U> tail = target;
target = null;
finished = true;
return tail;
}

private boolean finishUnless(boolean cont) {
if(cont)
return true;
@Override
public void forEachRemaining(Consumer<? super U> action) {
if(!init())
return;
TailCallSpliterator.forEachWithTail(target, action);
target = null;
finished = true;
return false;
}

@Override
public Spliterator<U> forEachOrTail(Consumer<? super U> action) {
return tryAdvanceOrTail(action);
}

private boolean init() {
if(finished)
return false;
if(target == null) {
Box<T> first = new Box<>(null);
Stream<U> stream = source.tryAdvance(x -> first.a = x) ? mapper.apply(first.a, StreamEx
.of(traverseTail(source))) : emptyMapper.get();
source = TailCallSpliterator.tryAdvanceWithTail(source, x -> first.a = x);
Stream<U> stream = source == null ? emptyMapper.get() : mapper.apply(first.a, StreamEx.of(source));
source = null;
mapper = null;
emptyMapper = null;
if(owner != null && mayHaveCloseAction(stream))
owner.onClose(stream::close);
delegateClose(owner, stream);
target = stream == null ? Spliterators.emptySpliterator() : stream.spliterator();
}
return true;
Expand All @@ -109,13 +104,4 @@ public long estimateSize() {
return 0;
return (target == null ? source : target).estimateSize();
}

@Override
public Spliterator<U> tail() {
if(!init())
return Spliterators.emptySpliterator();
Spliterator<U> t = target;
finishUnless(false);
return t;
}
}
2 changes: 1 addition & 1 deletion src/main/java/one/util/streamex/IntStreamEx.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ StreamFactory strategy() {

final IntStreamEx delegate(Spliterator.OfInt spliterator) {
return strategy().newIntStreamEx(
StreamSupport.intStream(spliterator, stream.isParallel()).onClose(stream::close));
delegateClose(StreamSupport.intStream(spliterator, stream.isParallel()), stream));
}

final IntStreamEx callWhile(IntPredicate predicate, int methodId) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/one/util/streamex/LongStreamEx.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ StreamFactory strategy() {

final LongStreamEx delegate(Spliterator.OfLong spliterator) {
return strategy().newLongStreamEx(
StreamSupport.longStream(spliterator, stream.isParallel()).onClose(stream::close));
delegateClose(StreamSupport.longStream(spliterator, stream.isParallel()), stream));
}

final LongStreamEx callWhile(LongPredicate predicate, int methodId) {
Expand Down
50 changes: 38 additions & 12 deletions src/main/java/one/util/streamex/PairSpliterator.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@
import java.util.function.LongConsumer;
import java.util.function.LongUnaryOperator;

import one.util.streamex.StreamExInternals.TailCallSpliterator;
import static one.util.streamex.StreamExInternals.*;

/**
* @author Tagir Valeev
*/
/* package */abstract class PairSpliterator<T, S extends Spliterator<T>, R, SS extends PairSpliterator<T, S, R, SS>>
extends CloneableSpliterator<R, SS> implements TailCallSpliterator<R> {
extends CloneableSpliterator<R, SS> {
static final int MODE_PAIRS = 0;
static final int MODE_MAP_FIRST = 1;
static final int MODE_MAP_LAST = 2;
Expand Down Expand Up @@ -132,16 +133,6 @@ void clear() {
}
}

@Override
public Spliterator<R> tail() {
if (mode != MODE_MAP_FIRST || right != EMPTY || left != null)
return this;
@SuppressWarnings("unchecked")
Spliterator<R> s = (Spliterator<R>)source;
source = null;
return s;
}

@Override
public long estimateSize() {
long size = source.estimateSize();
Expand Down Expand Up @@ -182,7 +173,7 @@ void finish(BiConsumer<T, T> fn, T cur) {
}

static class PSOfRef<T, R> extends PairSpliterator<T, Spliterator<T>, R, PSOfRef<T, R>> implements
Consumer<T> {
Consumer<T>, TailCallSpliterator<R> {
private static final Object HEAD_TAIL = new Object();

private final BiFunction<? super T, ? super T, ? extends R> mapper;
Expand Down Expand Up @@ -246,6 +237,41 @@ public void forEachRemaining(Consumer<? super R> action) {
});
finish(fn, cur);
}

@Override
public Spliterator<R> tryAdvanceOrTail(Consumer<? super R> action) {
if (mode != MODE_MAP_FIRST || right != EMPTY) {
return tryAdvance(action) ? this : null;
}
if (left != null) {
Sink<T> l = left;
left = null;
source = TailCallSpliterator.tryAdvanceWithTail(source, this);
if (source == null) {
right = null;
return null;
}
if (l.push(cur, fn(action), false))
return this;
}
@SuppressWarnings("unchecked")
Spliterator<R> s = (Spliterator<R>)source;
source = null;
return s;
}

@Override
public Spliterator<R> forEachOrTail(Consumer<? super R> action) {
if(mode != MODE_MAP_FIRST || right != EMPTY) {
forEachRemaining(action);
return null;
}
while (true) {
Spliterator<R> tail = tryAdvanceOrTail(action);
if (tail != this)
return tail;
}
}
}

static final class PSOfInt extends PairSpliterator<Integer, Spliterator.OfInt, Integer, PSOfInt> implements
Expand Down
Loading

0 comments on commit b43e512

Please sign in to comment.