This repository has been archived on 2021-12-05. You can view files and clone it, but cannot push or open issues or pull requests.
java-nio-server/src/main/java/com/jenkov/nioserver/QueueIntFlip.java

158 lines
4.3 KiB
Java

package com.jenkov.nioserver;
/**
* Same as QueueFillCount, except that QueueFlip uses a flip flag to keep track
* of when the internal writePos has "overflowed" (meaning it goes back to 0).
* Other than that, the two implementations are very similar in
* functionality.<br>
* <br>
* One additional difference is that QueueFlip has an available() method, where
* this is a public variable in QueueFillCount.<br>
* <br>
* Project: <strong>java-nio-server</strong><br>
* File: <strong>QueueIntFlip.java</strong><br>
* Created: <strong>18 Oct 2015</strong><br>
*
* @author jjenkov
*/
public class QueueIntFlip {
public int[] elements;
public int capacity;
public int writePos;
public int readPos;
public boolean flipped;
public QueueIntFlip(int capacity) {
this.capacity = capacity;
elements = new int[capacity]; // TODO: get from TypeAllocator ?
}
public void reset() {
writePos = 0;
readPos = 0;
flipped = false;
}
public int available() { return flipped ? capacity - readPos + writePos : writePos - readPos; }
public int remainingCapacity() { return flipped ? readPos - writePos : capacity - writePos; }
public boolean put(int element) {
if (!flipped) {
if (writePos == capacity) {
writePos = 0;
flipped = true;
if (writePos < readPos) {
elements[writePos++] = element;
return true;
} else return false;
} else {
elements[writePos++] = element;
return true;
}
} else {
if (writePos < readPos) {
elements[writePos++] = element;
return true;
} else return false;
}
}
public int put(int[] newElements, int length) {
int newElementsReadPos = 0;
if (!flipped) {
// readPos lower than writePos - free sections are:
// 1) from writePos to capacity
// 2) from 0 to readPos
if (length <= capacity - writePos) {
// new elements fit into top of elements array - copy directly
for (; newElementsReadPos < length; newElementsReadPos++)
elements[writePos++] = newElements[newElementsReadPos];
return newElementsReadPos;
} else {
// new elements must be divided between top and bottom of elements array
// writing to top
for (; writePos < capacity; writePos++)
elements[writePos] = newElements[newElementsReadPos++];
// writing to bottom
this.writePos = 0;
this.flipped = true;
int endPos = Math.min(readPos, length - newElementsReadPos);
for (; writePos < endPos; writePos++)
this.elements[writePos] = newElements[newElementsReadPos++];
return newElementsReadPos;
}
} else {
// readPos higher than writePos - free sections are:
// 1) from writePos to readPos
int endPos = Math.min(readPos, writePos + length);
for (; writePos < endPos; writePos++)
elements[writePos] = newElements[newElementsReadPos++];
return newElementsReadPos;
}
}
public int take() {
if (!flipped) return readPos < writePos ? elements[readPos++] : -1;
else {
if (readPos == capacity) {
readPos = 0;
flipped = false;
return readPos < writePos ? elements[readPos++] : -1;
} else return elements[readPos++];
}
}
public int take(int[] into, int length) {
int intoWritePos = 0;
if (!flipped) {
// writePos higher than readPos - available section is writePos - readPos
int endPos = Math.min(writePos, readPos + length);
for (; readPos < endPos; readPos++)
into[intoWritePos++] = elements[readPos];
return intoWritePos;
} else {
// readPos higher than writePos - available sections are top + bottom of
// elements array
if (length <= capacity - readPos) {
// length is lower than the elements available at the top of the elements array
// - copy directly
for (; intoWritePos < length; intoWritePos++)
into[intoWritePos] = elements[readPos++];
return intoWritePos;
} else {
// length is higher than elements available at the top of the elements array
// split copy into a copy from both top and bottom of elements array.
// copy from top
for (; readPos < capacity; readPos++)
into[intoWritePos++] = elements[readPos];
// copy from bottom
readPos = 0;
flipped = false;
int endPos = Math.min(writePos, length - intoWritePos);
for (; readPos < endPos; readPos++)
into[intoWritePos++] = elements[readPos];
return intoWritePos;
}
}
}
}