mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Implement ArrayBlockingQueue
This commit is contained in:
parent
ec3724b2bc
commit
28e17af500
|
@ -313,6 +313,7 @@ public class TObject {
|
|||
public final void waitImpl(long timeout, int nanos, final AsyncCallback<Void> callback) {
|
||||
final NotifyListenerImpl listener = new NotifyListenerImpl(this, callback, monitor.count);
|
||||
monitor.notifyListeners.add(listener);
|
||||
TThread.currentThread().interruptHandler = listener;
|
||||
if (timeout > 0 || nanos > 0) {
|
||||
listener.timerId = Platform.schedule(listener, timeout >= Integer.MAX_VALUE ? Integer.MAX_VALUE
|
||||
: (int) timeout);
|
||||
|
|
|
@ -31,7 +31,7 @@ public class TThread extends TObject implements TRunnable {
|
|||
private int yieldCount;
|
||||
private final Object finishedLock = new Object();
|
||||
private boolean interruptedFlag;
|
||||
private TThreadInterruptHandler interruptHandler;
|
||||
public TThreadInterruptHandler interruptHandler;
|
||||
|
||||
private TString name;
|
||||
private boolean alive = true;
|
||||
|
|
|
@ -18,11 +18,6 @@ package org.teavm.classlib.java.util;
|
|||
import java.util.Arrays;
|
||||
import org.teavm.classlib.java.lang.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
* @param <E>
|
||||
*/
|
||||
public class TArrayDeque<E> extends TAbstractCollection<E> implements TDeque<E> {
|
||||
private int version;
|
||||
private Object[] array;
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.util;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
* @param <E>
|
||||
*/
|
||||
public interface TQueue<E> extends TCollection<E> {
|
||||
boolean offer(E e);
|
||||
|
||||
|
|
|
@ -0,0 +1,495 @@
|
|||
/*
|
||||
* Copyright 2018 konsoletyper.
|
||||
*
|
||||
* 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 org.teavm.classlib.java.util.concurrent;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import org.teavm.classlib.java.lang.TInterruptedException;
|
||||
import org.teavm.classlib.java.lang.TThread;
|
||||
import org.teavm.classlib.java.lang.TThreadInterruptHandler;
|
||||
import org.teavm.classlib.java.util.TAbstractQueue;
|
||||
import org.teavm.classlib.java.util.TCollection;
|
||||
import org.teavm.classlib.java.util.TIterator;
|
||||
import org.teavm.interop.Async;
|
||||
import org.teavm.interop.Sync;
|
||||
import org.teavm.platform.Platform;
|
||||
import org.teavm.platform.PlatformQueue;
|
||||
import org.teavm.platform.PlatformRunnable;
|
||||
import org.teavm.platform.async.AsyncCallback;
|
||||
|
||||
public class TArrayBlockingQueue<E> extends TAbstractQueue<E> implements TBlockingQueue<E> {
|
||||
private Object[] array;
|
||||
private int head;
|
||||
private int tail;
|
||||
private PlatformQueue<WaitHandler> waitHandlers;
|
||||
|
||||
public TArrayBlockingQueue(int capacity) {
|
||||
this(capacity, false);
|
||||
}
|
||||
|
||||
public TArrayBlockingQueue(int capacity, boolean fair) {
|
||||
if (capacity < 1) {
|
||||
throw new IllegalArgumentException("Capacity must be >= 1");
|
||||
}
|
||||
array = new Object[capacity];
|
||||
}
|
||||
|
||||
public TArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) {
|
||||
if (capacity < 1 || capacity < Objects.requireNonNull(c).size()) {
|
||||
throw new IllegalArgumentException("Capacity must be at least 1 or collection's size");
|
||||
}
|
||||
if (c.size() > capacity) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
array = new Object[capacity];
|
||||
|
||||
int index = 0;
|
||||
for (E e : c) {
|
||||
array[index++] = Objects.requireNonNull(e);
|
||||
}
|
||||
tail = c.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
Objects.requireNonNull(e);
|
||||
if (isFull()) {
|
||||
throw new IllegalStateException("This blocking queue is full");
|
||||
}
|
||||
addImpl(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(E e) {
|
||||
Objects.requireNonNull(e);
|
||||
if (isFull()) {
|
||||
return false;
|
||||
}
|
||||
addImpl(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(E e) throws InterruptedException {
|
||||
Objects.requireNonNull(e);
|
||||
while (isFull()) {
|
||||
waitForChange(0);
|
||||
}
|
||||
addImpl(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean offer(E e, long timeout, TTimeUnit unit) throws InterruptedException {
|
||||
Objects.requireNonNull(e);
|
||||
if (isFull()) {
|
||||
long timeLimit = System.currentTimeMillis() + unit.toMillis(timeout);
|
||||
while (isFull()) {
|
||||
if (!waitForChange(timeLimit)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
addImpl(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E poll() {
|
||||
if (isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return removeImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E take() throws InterruptedException {
|
||||
while (isEmpty()) {
|
||||
waitForChange(0);
|
||||
}
|
||||
return removeImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E poll(long timeout, TTimeUnit unit) throws InterruptedException {
|
||||
if (isEmpty()) {
|
||||
long timeLimit = System.currentTimeMillis() + unit.toMillis(timeout);
|
||||
while (isEmpty()) {
|
||||
if (!waitForChange(timeLimit)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return removeImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public E peek() {
|
||||
if (isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return (E) array[head];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
if (head < tail) {
|
||||
return tail - head;
|
||||
} else if (array[head] != null) {
|
||||
return tail + array.length - head;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return head == tail && array[head] == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int remainingCapacity() {
|
||||
return array.length - size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
} else if (head < tail) {
|
||||
for (int i = head; i < tail; ++i) {
|
||||
if (array[i].equals(o)) {
|
||||
removeAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
for (int i = head; i < array.length; ++i) {
|
||||
if (array[i].equals(o)) {
|
||||
removeAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < tail; ++i) {
|
||||
if (array[i].equals(o)) {
|
||||
removeAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
} else if (head < tail) {
|
||||
for (int i = head; i < tail; ++i) {
|
||||
if (array[i].equals(o)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
for (int i = head; i < array.length; ++i) {
|
||||
if (array[i].equals(o)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < tail; ++i) {
|
||||
if (array[i].equals(o)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
if (isEmpty()) {
|
||||
return new Object[0];
|
||||
} else if (head < tail) {
|
||||
return Arrays.copyOfRange(array, head, tail);
|
||||
} else {
|
||||
Object[] result = new Object[size()];
|
||||
System.arraycopy(array, head, result, 0, array.length - head);
|
||||
System.arraycopy(array, 0, result, array.length - head, tail);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "SuspiciousSystemArraycopy" })
|
||||
public <T> T[] toArray(T[] a) {
|
||||
if (isEmpty()) {
|
||||
if (a.length > 0) {
|
||||
a[0] = null;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
int size = size();
|
||||
if (size > a.length) {
|
||||
a = (T[]) Array.newInstance(a.getClass().getComponentType(), size);
|
||||
} else if (size < a.length) {
|
||||
a[size] = null;
|
||||
}
|
||||
|
||||
if (head < tail) {
|
||||
System.arraycopy(array, head, a, 0, size);
|
||||
} else {
|
||||
System.arraycopy(array, head, a, 0, array.length - head);
|
||||
System.arraycopy(array, 0, a, array.length - head, tail);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if (isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (head < tail) {
|
||||
for (int i = head; i < tail; ++i) {
|
||||
array[i] = null;
|
||||
}
|
||||
} else {
|
||||
for (int i = head; i < array.length; ++i) {
|
||||
array[i] = null;
|
||||
}
|
||||
for (int i = 0; i < tail; ++i) {
|
||||
array[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
head = 0;
|
||||
tail = 0;
|
||||
notifyChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int drainTo(TCollection<? super E> c) {
|
||||
return drainTo(c, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int drainTo(TCollection<? super E> c, int maxElements) {
|
||||
if (c == this) {
|
||||
throw new IllegalArgumentException("The specified collection is this queue");
|
||||
}
|
||||
if (isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
Objects.requireNonNull(c);
|
||||
maxElements = Math.min(maxElements, size());
|
||||
if (maxElements < tail) {
|
||||
for (int i = 0; i < maxElements; ++i) {
|
||||
drainSingleTo(c);
|
||||
}
|
||||
notifyChange();
|
||||
} else {
|
||||
int remaining = maxElements - (array.length - head);
|
||||
while (head < array.length) {
|
||||
drainSingleTo(c);
|
||||
}
|
||||
head = 0;
|
||||
while (remaining-- > 0) {
|
||||
drainSingleTo(c);
|
||||
}
|
||||
notifyChange();
|
||||
}
|
||||
return maxElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TIterator<E> iterator() {
|
||||
return new TIterator<E>() {
|
||||
int index = head;
|
||||
int removeIndex = -1;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return array[index] != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
removeIndex = index;
|
||||
@SuppressWarnings("unchecked")
|
||||
E result = (E) array[index++];
|
||||
if (result == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
if (index == array.length) {
|
||||
index = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (removeIndex < 0 || array[removeIndex] == null) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
removeAt(removeIndex);
|
||||
removeIndex = -1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void removeAt(int index) {
|
||||
if (index < tail) {
|
||||
shiftElements(index, tail);
|
||||
--tail;
|
||||
} else {
|
||||
shiftElements(index, array.length);
|
||||
array[array.length - 1] = array[0];
|
||||
shiftElements(0, tail);
|
||||
if (--tail < 0) {
|
||||
tail = array.length;
|
||||
}
|
||||
}
|
||||
array[tail] = null;
|
||||
notifyChange();
|
||||
}
|
||||
|
||||
private void drainSingleTo(TCollection<? super E> c) {
|
||||
@SuppressWarnings("unchecked")
|
||||
E e = (E) array[head];
|
||||
array[head++] = null;
|
||||
c.add(e);
|
||||
}
|
||||
|
||||
private void shiftElements(int from, int to) {
|
||||
int remaining = to - from - 1;
|
||||
if (remaining > 0) {
|
||||
System.arraycopy(array, from + 1, array, from, remaining);
|
||||
}
|
||||
}
|
||||
|
||||
@Sync
|
||||
private void addImpl(E e) {
|
||||
array[tail++] = e;
|
||||
if (tail == array.length) {
|
||||
tail = 0;
|
||||
}
|
||||
notifyChange();
|
||||
}
|
||||
|
||||
@Sync
|
||||
private E removeImpl() {
|
||||
@SuppressWarnings("unchecked")
|
||||
E result = (E) array[head];
|
||||
array[head++] = null;
|
||||
if (head == array.length) {
|
||||
head = 0;
|
||||
}
|
||||
notifyChange();
|
||||
return result;
|
||||
}
|
||||
|
||||
private void notifyChange() {
|
||||
if (waitHandlers == null) {
|
||||
return;
|
||||
}
|
||||
if (waitHandlers != null) {
|
||||
while (!waitHandlers.isEmpty()) {
|
||||
Platform.postpone(() -> waitHandlers.remove().changed());
|
||||
}
|
||||
waitHandlers = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Async
|
||||
private native Boolean waitForChange(long timeLimit) throws InterruptedException;
|
||||
|
||||
private void waitForChange(long timeLimit, AsyncCallback<Boolean> callback) {
|
||||
if (waitHandlers == null) {
|
||||
waitHandlers = Platform.createQueue();
|
||||
}
|
||||
|
||||
WaitHandler handler = new WaitHandler(callback);
|
||||
waitHandlers.add(handler);
|
||||
if (timeLimit > 0) {
|
||||
int timeout = Math.max(0, (int) (timeLimit - System.currentTimeMillis()));
|
||||
handler.timerId = Platform.schedule(handler, timeout);
|
||||
} else {
|
||||
handler.timerId = -1;
|
||||
}
|
||||
|
||||
TThread.currentThread().interruptHandler = handler;
|
||||
}
|
||||
|
||||
class WaitHandler implements PlatformRunnable, TThreadInterruptHandler {
|
||||
AsyncCallback<Boolean> callback;
|
||||
boolean complete;
|
||||
int timerId;
|
||||
|
||||
WaitHandler(AsyncCallback<Boolean> callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (complete()) {
|
||||
return;
|
||||
}
|
||||
callback.complete(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void interrupted() {
|
||||
if (complete()) {
|
||||
return;
|
||||
}
|
||||
callback.error(new TInterruptedException());
|
||||
}
|
||||
|
||||
private boolean complete() {
|
||||
if (complete) {
|
||||
return true;
|
||||
}
|
||||
complete = true;
|
||||
if (timerId >= 0) {
|
||||
Platform.killSchedule(timerId);
|
||||
timerId = -1;
|
||||
}
|
||||
TThread.currentThread().interruptHandler = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
void changed() {
|
||||
if (complete()) {
|
||||
return;
|
||||
}
|
||||
callback.complete(true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFull() {
|
||||
return head == tail && array[head] != null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2018 konsoletyper.
|
||||
*
|
||||
* 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 org.teavm.classlib.java.util.concurrent;
|
||||
|
||||
import org.teavm.classlib.java.util.TCollection;
|
||||
import org.teavm.classlib.java.util.TQueue;
|
||||
|
||||
public interface TBlockingQueue<E> extends TQueue<E> {
|
||||
void put(E e) throws InterruptedException;
|
||||
|
||||
boolean offer(E e, long timeout, TTimeUnit unit) throws InterruptedException;
|
||||
|
||||
E take() throws InterruptedException;
|
||||
|
||||
E poll(long timeout, TTimeUnit unit) throws InterruptedException;
|
||||
|
||||
int remainingCapacity();
|
||||
|
||||
int drainTo(TCollection<? super E> c);
|
||||
|
||||
int drainTo(TCollection<? super E> c, int maxElements);
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2018 konsoletyper.
|
||||
*
|
||||
* 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 org.teavm.classlib.java.util.concurrent;
|
||||
|
||||
public enum TTimeUnit {
|
||||
NANOSECONDS(1),
|
||||
MICROSECONDS(1_000),
|
||||
MILLISECONDS(1_000_000),
|
||||
SECONDS(1_000_000_000),
|
||||
MINUTES(60_000_000_000L),
|
||||
HOURS(3_600_000_000_000L),
|
||||
DAYS(24 * 3_600_000_000_000L);
|
||||
|
||||
private long nanoseconds;
|
||||
|
||||
TTimeUnit(long nanoseconds) {
|
||||
this.nanoseconds = nanoseconds;
|
||||
}
|
||||
|
||||
public long convert(long sourceDuration, TTimeUnit sourceUnit) {
|
||||
long sourceNanos = sourceUnit.nanoseconds;
|
||||
long targetNanos = nanoseconds;
|
||||
if (sourceNanos < targetNanos) {
|
||||
return sourceDuration * (targetNanos / sourceNanos);
|
||||
} else {
|
||||
return sourceDuration / (sourceNanos / targetNanos);
|
||||
}
|
||||
}
|
||||
|
||||
public long toNanos(long duration) {
|
||||
return duration * nanoseconds;
|
||||
}
|
||||
|
||||
public long toMicros(long duration) {
|
||||
return MICROSECONDS.convert(duration, this);
|
||||
}
|
||||
|
||||
public long toMillis(long duration) {
|
||||
return MILLISECONDS.convert(duration, this);
|
||||
}
|
||||
|
||||
public long toSeconds(long duration) {
|
||||
return SECONDS.convert(duration, this);
|
||||
}
|
||||
|
||||
public long toMinutes(long duration) {
|
||||
return MINUTES.convert(duration, this);
|
||||
}
|
||||
|
||||
public long toHours(long duration) {
|
||||
return HOURS.convert(duration, this);
|
||||
}
|
||||
|
||||
public long toDays(long duration) {
|
||||
return DAYS.convert(duration, this);
|
||||
}
|
||||
|
||||
public void timedWait(Object obj, long timeout) throws InterruptedException {
|
||||
obj.wait(toMillis(timeout));
|
||||
}
|
||||
|
||||
public void timedJoin(Thread thread, long timeout) throws InterruptedException {
|
||||
thread.join(toMillis(timeout));
|
||||
}
|
||||
|
||||
public void sleep(long timeout) throws InterruptedException {
|
||||
Thread.sleep(toMillis(timeout));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright 2018 Alexey Andreev.
|
||||
*
|
||||
* 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 org.teavm.classlib.java.util.concurrent;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.teavm.junit.TeaVMTestRunner;
|
||||
|
||||
@RunWith(TeaVMTestRunner.class)
|
||||
public class ArrayBlockingQueueTest {
|
||||
@Test
|
||||
public void constructed() {
|
||||
List<Integer> list = Arrays.asList(2, 3, 5);
|
||||
|
||||
try {
|
||||
new ArrayBlockingQueue<>(2, false, list);
|
||||
fail("IAE expected");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
try {
|
||||
new ArrayBlockingQueue<>(0);
|
||||
fail("IAE expected");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
try {
|
||||
new ArrayBlockingQueue<>(1, false, null);
|
||||
fail("IAE expected");
|
||||
} catch (NullPointerException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5, false, list);
|
||||
assertEquals(3, queue.size());
|
||||
assertEquals(2, queue.remainingCapacity());
|
||||
|
||||
assertEquals(2, queue.poll().intValue());
|
||||
assertEquals(3, queue.poll().intValue());
|
||||
assertEquals(5, queue.poll().intValue());
|
||||
assertNull(queue.poll());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleThread() {
|
||||
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
|
||||
queue.add(1);
|
||||
queue.add(2);
|
||||
queue.add(3);
|
||||
assertEquals(1, queue.poll().intValue());
|
||||
queue.add(4);
|
||||
assertEquals(2, queue.poll().intValue());
|
||||
assertEquals(3, queue.poll().intValue());
|
||||
assertEquals(4, queue.poll().intValue());
|
||||
assertNull(queue.poll());
|
||||
|
||||
queue.add(5);
|
||||
assertEquals(5, queue.poll().intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blockingAddition() throws InterruptedException {
|
||||
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(1);
|
||||
assertTrue(queue.offer(1));
|
||||
assertFalse(queue.offer(2));
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(150);
|
||||
} catch (InterruptedException e) {
|
||||
// Do nothing
|
||||
}
|
||||
queue.poll();
|
||||
}).start();
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
queue.put(3);
|
||||
long end = System.currentTimeMillis();
|
||||
assertTrue(start + 50 < end && start + 250 > end);
|
||||
|
||||
assertEquals(3, queue.remove().intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blockingRemoval() throws InterruptedException {
|
||||
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
|
||||
assertNull(queue.poll());
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(300);
|
||||
} catch (InterruptedException e) {
|
||||
// Do nothing
|
||||
}
|
||||
queue.add(1);
|
||||
queue.add(2);
|
||||
}).start();
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
int a = queue.take();
|
||||
long end = System.currentTimeMillis();
|
||||
int b = queue.take();
|
||||
|
||||
assertTrue(start + 100 < end && start + 500 > end);
|
||||
assertEquals(1, a);
|
||||
assertEquals(2, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shiftQueueSize() {
|
||||
assertEquals(6, shiftQueue().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void remove() {
|
||||
BlockingQueue<Integer> queue = simpleQueue();
|
||||
assertTrue(queue.remove(2));
|
||||
assertEquals(2, queue.size());
|
||||
assertEquals(1, queue.poll().intValue());
|
||||
assertEquals(3, queue.poll().intValue());
|
||||
assertNull(queue.poll());
|
||||
|
||||
queue = shiftQueue();
|
||||
assertTrue(queue.remove(1));
|
||||
assertEquals(5, queue.size());
|
||||
assertEquals(0, queue.poll().intValue());
|
||||
assertEquals(2, queue.poll().intValue());
|
||||
assertEquals(3, queue.poll().intValue());
|
||||
assertEquals(4, queue.poll().intValue());
|
||||
assertEquals(5, queue.poll().intValue());
|
||||
assertNull(queue.poll());
|
||||
|
||||
queue = shiftQueue();
|
||||
assertTrue(queue.remove(4));
|
||||
assertEquals(5, queue.size());
|
||||
assertEquals(0, queue.poll().intValue());
|
||||
assertEquals(1, queue.poll().intValue());
|
||||
assertEquals(2, queue.poll().intValue());
|
||||
assertEquals(3, queue.poll().intValue());
|
||||
assertEquals(5, queue.poll().intValue());
|
||||
assertNull(queue.poll());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dumpsToArray() {
|
||||
BlockingQueue<Integer> queue = simpleQueue();
|
||||
assertArrayEquals(new Integer[] { 1, 2, 3 }, queue.toArray());
|
||||
|
||||
queue = shiftQueue();
|
||||
assertArrayEquals(new Integer[] { 0, 1, 2, 3, 4, 5 }, queue.toArray());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dumpsToTypedArray() {
|
||||
BlockingQueue<Integer> queue = simpleQueue();
|
||||
assertArrayEquals(new Integer[] { 1, 2, 3 }, queue.toArray(new Integer[3]));
|
||||
assertArrayEquals(new Integer[] { 1, 2, 3 }, queue.toArray(new Integer[1]));
|
||||
|
||||
Integer[] array = new Integer[] { 10, 11, 12, 13, 14, 15 };
|
||||
assertArrayEquals(new Integer[] { 1, 2, 3, null, 14, 15 }, queue.toArray(array));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void drains() {
|
||||
BlockingQueue<Integer> queue = simpleQueue();
|
||||
List<Integer> target = new ArrayList<>();
|
||||
assertEquals(2, queue.drainTo(target, 2));
|
||||
assertEquals(Arrays.asList(1, 2), target);
|
||||
|
||||
queue = simpleQueue();
|
||||
target.clear();
|
||||
assertEquals(3, queue.drainTo(target, 4));
|
||||
assertEquals(Arrays.asList(1, 2, 3), target);
|
||||
|
||||
queue = shiftQueue();
|
||||
target.clear();
|
||||
assertEquals(2, queue.drainTo(target, 2));
|
||||
assertEquals(Arrays.asList(0, 1), target);
|
||||
|
||||
queue = shiftQueue();
|
||||
target.clear();
|
||||
assertEquals(4, queue.drainTo(target, 4));
|
||||
assertEquals(Arrays.asList(0, 1, 2, 3), target);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iterator() {
|
||||
BlockingQueue<Integer> queue = simpleQueue();
|
||||
assertEquals(Arrays.asList(1, 2, 3), new ArrayList<>(queue));
|
||||
|
||||
queue = shiftQueue();
|
||||
assertEquals(Arrays.asList(0, 1, 2, 3, 4, 5), new ArrayList<>(queue));
|
||||
}
|
||||
|
||||
private BlockingQueue<Integer> simpleQueue() {
|
||||
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
|
||||
queue.add(0);
|
||||
queue.remove();
|
||||
queue.add(1);
|
||||
queue.add(2);
|
||||
queue.add(3);
|
||||
return queue;
|
||||
}
|
||||
|
||||
private BlockingQueue<Integer> shiftQueue() {
|
||||
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
queue.add(i);
|
||||
}
|
||||
while (!queue.isEmpty()) {
|
||||
queue.remove();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
queue.add(i);
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user