158 lines
4.3 KiB
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;
|
|
}
|
|
}
|
|
}
|
|
} |