Synchronize the remote counter, and correct an issue with rest() concerning generation IDs

This commit is contained in:
Manevolent
2018-10-02 08:58:29 -04:00
parent 6bf85e3c6c
commit a85904555e
@@ -1146,30 +1146,39 @@ public abstract class AbstractTeamspeakClientSocket
@Override @Override
public int getGeneration(int packetId) { public int getGeneration(int packetId) {
Pair<Integer, Integer> bufferStartCopy;
Pair<Integer, Integer> bufferEndCopy;
// Shorter synchronization
synchronized (this) {
bufferStartCopy = this.bufferStart;
bufferEndCopy = this.bufferEnd;
}
packetId %= generationSize; packetId %= generationSize;
// find if right of the start and within the start's bounds // find if right of the start and within the start's bounds
if (packetId >= bufferStart.getValue() if (packetId >= bufferStartCopy.getValue()
&& packetId < bufferStart.getValue() + bufferSize && packetId < bufferStartCopy.getValue() + bufferSize
&& packetId < generationSize) { && packetId < generationSize) {
return bufferStart.getKey(); return bufferStartCopy.getKey();
} }
// find if left of end and within the end's bounds // find if left of end and within the end's bounds
if (packetId <= bufferEnd.getValue() if (packetId <= bufferEndCopy.getValue()
&& packetId > 0 && packetId > 0
&& packetId > bufferEnd.getValue() - bufferSize && packetId > bufferEndCopy.getValue() - bufferSize
&& packetId < generationSize) { && packetId < generationSize) {
return bufferEnd.getKey(); return bufferEndCopy.getKey();
} }
// find if outside of buffer to the right // find if outside of buffer to the right
if (packetId > bufferEnd.getValue()) if (packetId > bufferEndCopy.getValue())
return bufferEnd.getKey(); // ahead in current generation return bufferEndCopy.getKey(); // ahead in current generation
// find if outside of buffer to the left // find if outside of buffer to the left
if (packetId < bufferStart.getValue()) if (packetId < bufferStartCopy.getValue())
return bufferEnd.getKey() + 1; // modulated wrap, ahead of current generation return bufferEndCopy.getKey() + 1; // modulated wrap, ahead of current generation
// should never arrive here. // should never arrive here.
throw new IllegalStateException(); throw new IllegalStateException();
@@ -1187,91 +1196,101 @@ public abstract class AbstractTeamspeakClientSocket
@Override @Override
public boolean put(int packetId) { public boolean put(int packetId) {
// find if right of the start and within the start's bounds synchronized (this) {
if (packetId >= bufferStart.getValue() // find if right of the start and within the start's bounds
&& packetId < bufferStart.getValue() + bufferSize if (packetId >= bufferStart.getValue()
&& packetId < generationSize) { && packetId < bufferStart.getValue() + bufferSize
latestPacketId = Math.max(latestPacketId, packetId); && packetId < generationSize) {
latestPacketId = Math.max(latestPacketId, packetId);
return putRelative(packetId - bufferStart.getValue(), bufferStart.getKey()); return putRelative(packetId - bufferStart.getValue(), bufferStart.getKey());
}
// find if left of end and within the end's bounds
if (packetId <= bufferEnd.getValue()
&& packetId >= 0
&& packetId > bufferEnd.getValue() - bufferSize
&& packetId < generationSize) {
latestPacketId = Math.max(latestPacketId, packetId);
return putRelative(bufferSize - (bufferEnd.getValue() - packetId) - 1, bufferEnd.getKey());
}
// distance the start position must move right by
int amountMoved = 0;
// find if outside of buffer to the right
if (packetId > bufferEnd.getValue()) { // slide buffer forward uniformly
amountMoved = packetId - bufferEnd.getValue();
}
// find if outside of buffer to the left
if (packetId < bufferStart.getValue()) { // start wrapping buffer or continue to do so
amountMoved =
(generationSize - bufferStart.getValue()) +
packetId + 1;
amountMoved -= bufferSize;
}
if (amountMoved > 0) { // should always be true
int toMove = Math.max(0, bufferSize - amountMoved);
if (toMove > 0 && toMove < bufferSize)
System.arraycopy(buffer, amountMoved, buffer, 0, toMove);
int toNullify = Math.max(0, Math.min(bufferSize, amountMoved));
for (int i = bufferSize - toNullify; i < bufferSize; i ++)
buffer[i] = null;
int bufferStartGeneration = bufferStart.getKey();
int bufferStartPosition = bufferStart.getValue();
bufferStartPosition += amountMoved;
if (bufferStartPosition >= generationSize) {
bufferStartPosition %= generationSize;
bufferStartGeneration ++;
} }
int bufferEndGeneration; // find if left of end and within the end's bounds
int bufferEndPosition = (bufferStartPosition + bufferSize - 1) % generationSize; if (packetId <= bufferEnd.getValue()
if (bufferEndPosition < bufferStartPosition) { && packetId >= 0
bufferEndGeneration = bufferStartGeneration + 1; && packetId > bufferEnd.getValue() - bufferSize
&& packetId < generationSize) {
latestPacketId = Math.max(latestPacketId, packetId);
return putRelative(bufferSize - (bufferEnd.getValue() - packetId) - 1, bufferEnd.getKey());
}
// distance the start position must move right by
int amountMoved = 0;
// find if outside of buffer to the right
if (packetId > bufferEnd.getValue()) { // slide buffer forward uniformly
amountMoved = packetId - bufferEnd.getValue();
}
// find if outside of buffer to the left
if (packetId < bufferStart.getValue()) { // start wrapping buffer or continue to do so
amountMoved =
(generationSize - bufferStart.getValue()) +
packetId + 1;
amountMoved -= bufferSize;
}
if (amountMoved > 0) { // should always be true
int toMove = Math.max(0, bufferSize - amountMoved);
if (toMove > 0 && toMove < bufferSize)
System.arraycopy(buffer, amountMoved, buffer, 0, toMove);
int toNullify = Math.max(0, Math.min(bufferSize, amountMoved));
for (int i = bufferSize - toNullify; i < bufferSize; i++)
buffer[i] = null;
int bufferStartGeneration = bufferStart.getKey();
int bufferStartPosition = bufferStart.getValue();
bufferStartPosition += amountMoved;
if (bufferStartPosition >= generationSize) {
bufferStartPosition %= generationSize;
bufferStartGeneration++;
}
int bufferEndGeneration;
int bufferEndPosition = (bufferStartPosition + bufferSize - 1) % generationSize;
if (bufferEndPosition < bufferStartPosition) {
bufferEndGeneration = bufferStartGeneration + 1;
} else
bufferEndGeneration = bufferStartGeneration;
this.bufferStart = new Pair<>(bufferStartGeneration, bufferStartPosition);
this.bufferEnd = new Pair<>(bufferEndGeneration, bufferEndPosition);
} else } else
bufferEndGeneration = bufferStartGeneration; throw new IllegalStateException();
this.bufferStart = new Pair<>(bufferStartGeneration, bufferStartPosition); // if we had to adjust the buffer size, recursively retry put
this.bufferEnd = new Pair<>(bufferEndGeneration, bufferEndPosition); this.latestPacketId = packetId;
} else
throw new IllegalStateException();
// if we had to adjust the buffer size, recursively retry put return put(packetId);
this.latestPacketId = packetId; }
return put(packetId);
} }
@Override @Override
public void reset() { public void reset() {
for (int i = 0; i < bufferSize; i ++) synchronized (this) {
buffer[i] = null; for (int i = 0; i < bufferSize; i++)
this.buffer[i] = null;
this.bufferStart = new Pair<>(0, 0);
this.bufferEnd = new Pair<>(0, bufferSize - 1);
this.latestPacketId = 0;
}
} }
private boolean putRelative(int index, int generation) { private boolean putRelative(int index, int generation) {
Integer existing = buffer[index]; synchronized (this) {
if (existing == null || existing != generation) { Integer existing = buffer[index];
buffer[index] = generation; if (existing == null || existing != generation) {
return true; buffer[index] = generation;
} else { return true;
return false; } else {
return false;
}
} }
} }
} }