/*
* Copyright (C) 2015 SoftIndex LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.datakernel.stream;
import io.datakernel.async.AsyncIterator;
import io.datakernel.async.IteratorCallback;
import io.datakernel.eventloop.Eventloop;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
* Represents AsyncIterator which can call its callbacks with next element in eventloop's thread
*
* @param <T> type of element in iterator
*/
public class AsyncIteratorWithSetter<T> implements AsyncIterator<T> {
private final Eventloop eventloop;
private IteratorCallback<T> callback;
private T next;
private boolean end;
private Exception exception;
/**
* Creates a new AsyncIteratorWithSetter with eventloop from argument
*/
public AsyncIteratorWithSetter(Eventloop eventloop) {
this.eventloop = eventloop;
}
/**
* Processes the next element with eventloop
*/
@Override
public void next(IteratorCallback<T> callback) {
if (next != null) {
sendNext(callback, next);
this.next = null;
} else if (end) {
end(callback);
} else if (exception != null) {
fireException(callback, exception);
this.exception = null;
} else {
this.callback = callback;
}
}
private void sendNext(final IteratorCallback<T> callback, final T next) {
eventloop.post(new Runnable() {
@Override
public void run() {
callback.setNext(next);
}
});
}
private void end(final IteratorCallback<T> callback) {
eventloop.post(new Runnable() {
@Override
public void run() {
callback.setEnd();
}
});
}
private void fireException(final IteratorCallback<T> callback, final Exception exception) {
eventloop.post(new Runnable() {
@Override
public void run() {
callback.setException(exception);
}
});
}
public void onNext(T item) {
checkState(next == null && !end && exception == null);
checkNotNull(item);
if (callback != null) {
sendNext(callback, item);
callback = null;
} else {
this.next = item;
}
}
public void onEnd() {
checkState(next == null && !end && exception == null);
if (callback != null) {
end(callback);
callback = null;
} else {
this.end = true;
}
}
public void onException(Exception exception) {
checkState(next == null && !end && this.exception == null);
if (callback != null) {
fireException(callback, exception);
callback = null;
} else {
this.exception = exception;
}
}
/**
* Returns new AsyncIteratorWithSetter with eventloop from argument
*
* @param <T> type of element from iterator
*/
public static <T> AsyncIteratorWithSetter<T> createAsyncIteratorWithSetter(Eventloop eventloop) {
return new AsyncIteratorWithSetter<>(eventloop);
}
}