mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 03:39:00 +00:00
Updates for RecvRingBuff.
This commit is contained in:
parent
16c27b0ce0
commit
f1db2972fd
@ -271,6 +271,13 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
|||||||
clientSession.onclose = function(evt) {
|
clientSession.onclose = function(evt) {
|
||||||
// [WARNING] The callback "onclose" might be called AFTER the webpage is refreshed with "1001 == evt.code".
|
// [WARNING] The callback "onclose" might be called AFTER the webpage is refreshed with "1001 == evt.code".
|
||||||
console.warn(`The WS clientSession is closed: evt=${JSON.stringify(evt)}, evt.code=${evt.code}`);
|
console.warn(`The WS clientSession is closed: evt=${JSON.stringify(evt)}, evt.code=${evt.code}`);
|
||||||
|
if (cc.sys.isNative) {
|
||||||
|
if (mapIns.frameDataLoggingEnabled) {
|
||||||
|
console.warn(`${mapIns._stringifyRdfIdToActuallyUsedInput()}
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
DelayNoMore.UdpSession.closeUdpSession();
|
||||||
|
}
|
||||||
switch (evt.code) {
|
switch (evt.code) {
|
||||||
case constants.RET_CODE.CLIENT_MISMATCHED_RENDER_FRAME:
|
case constants.RET_CODE.CLIENT_MISMATCHED_RENDER_FRAME:
|
||||||
break;
|
break;
|
||||||
@ -312,15 +319,13 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
|||||||
default:
|
default:
|
||||||
if (cc.sys.isNative) {
|
if (cc.sys.isNative) {
|
||||||
// [WARNING] This could be a BUG in CocosCreator JSB implementation of WebSocket client, the "evt.code" is always "undefined" in the "onclose" callback!
|
// [WARNING] This could be a BUG in CocosCreator JSB implementation of WebSocket client, the "evt.code" is always "undefined" in the "onclose" callback!
|
||||||
if (mapIns.frameDataLoggingEnabled) {
|
if (window.ALL_BATTLE_STATES.IN_SETTLEMENT != mapIns.battleState && window.ALL_BATTLE_STATES.IN_DISMISSAL != mapIns.battleState) {
|
||||||
console.warn(`${mapIns._stringifyRdfIdToActuallyUsedInput()}
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
DelayNoMore.UdpSession.closeUdpSession();
|
|
||||||
mapIns.popupSimplePressToGo("Disconnected unexpectedly, please retry", false, () => {
|
mapIns.popupSimplePressToGo("Disconnected unexpectedly, please retry", false, () => {
|
||||||
window.clearLocalStorageAndBackToLoginScene(true);
|
window.clearLocalStorageAndBackToLoginScene(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
File diff suppressed because one or more lines are too long
@ -32,20 +32,38 @@ SendWork* SendRingBuff::pop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Recving
|
// Recving
|
||||||
|
bool isFullWithLoadedVals(int n, int oldCnt, int oldSt, int oldEd) {
|
||||||
|
return (n <= oldCnt) || (n > oldCnt && 0 < oldCnt && oldEd == oldSt);
|
||||||
|
}
|
||||||
|
|
||||||
void RecvRingBuff::put(char* newBytes, size_t newBytesLen) {
|
void RecvRingBuff::put(char* newBytes, size_t newBytesLen) {
|
||||||
RecvWork* slotEle = (&eles[ed.load()]); // Save for later update
|
RecvWork* slotEle = (&eles[ed.load()]); // Save for later update
|
||||||
|
|
||||||
|
// "RecvRingBuff.ed" is only accessed in "UvRecvThread", thus the order of it relative to the other two is not important.
|
||||||
|
int oldEd = ed.load();
|
||||||
|
|
||||||
|
// We want to increase the success rate of "pop()" if it's being executed by "GameThread/pollUdpRecvRingBuff", thus the below order of loading is IMPORTANT, i.e. load "cnt" first because it's decremented earlier than "st" being incremented.
|
||||||
int oldCnt = cnt.load();
|
int oldCnt = cnt.load();
|
||||||
int oldSt = st.load(); // Used to guard against "cnt decremented in pop(...), but st not yet incremented and thus return value not yet copied to avoid contamination"
|
int oldSt = st.load(); // Used to guard against "cnt decremented in pop(...), but st not yet incremented and thus return value not yet copied to avoid contamination"
|
||||||
int tried = 0;
|
int tried = 0;
|
||||||
while (n <= oldCnt && !ed.compare_exchange_weak(oldSt, oldSt) && 3 > tried) {
|
/*
|
||||||
|
1. When "n <= oldCnt", it's implied that "oldEd == oldSt";
|
||||||
|
2. When "n > oldCnt", it might still be true that "oldEd == oldSt" if "pop()" hasn't successfully incremented "st" due to any reason;
|
||||||
|
3. When "oldEd == oldSt", it doesn't imply anything useful, because any of the following could be true
|
||||||
|
- a. "n <= oldCnt", i.e. the ringbuff is full
|
||||||
|
- b. "n > oldCnt && 0 < oldCnt" during the execution of "pop()", i.e. the ringbuff is still effectively full
|
||||||
|
- c. "n > oldCnt && 0 == oldCnt", i.e. the ringbuff is empty
|
||||||
|
*/
|
||||||
|
bool isFull = isFullWithLoadedVals(n, oldCnt, oldSt, oldEd);
|
||||||
|
while (isFull && 3 > tried) {
|
||||||
// Make room for the new element
|
// Make room for the new element
|
||||||
this->pop(NULL);
|
this->pop(NULL);
|
||||||
oldCnt = cnt.load(); // If "pop()" above failed, it'd only be due to concurrent calls to "pop()", either way the updated "cnt" should be good to go
|
oldCnt = cnt.load(); // If "pop()" above failed, it'd only be due to concurrent calls to "pop()", either way the updated "cnt" should be good to go
|
||||||
oldSt = st.load();
|
oldSt = st.load();
|
||||||
|
isFull = isFullWithLoadedVals(n, oldCnt, oldSt, oldEd);
|
||||||
++tried;
|
++tried;
|
||||||
}
|
}
|
||||||
if (n <= oldCnt && !ed.compare_exchange_weak(oldSt, oldSt) && 3 == tried) {
|
if (isFull && 3 == tried) {
|
||||||
// Failed silently, UDP packet can be dropped.
|
// Failed silently, UDP packet can be dropped.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -56,11 +74,13 @@ void RecvRingBuff::put(char* newBytes, size_t newBytesLen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No need to compare-and-swap, only "UvRecvThread" will access "RecvRingBuff.ed".
|
// No need to compare-and-swap, only "UvRecvThread" will access "RecvRingBuff.ed".
|
||||||
ed++;
|
int newEd = oldEd+1;
|
||||||
if (ed >= n) {
|
if (newEd >= n) {
|
||||||
ed -= n; // Deliberately not using "%" operator for performance concern
|
newEd -= n; // Deliberately not using "%" operator for performance concern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ed.compare_exchange_weak(oldEd, newEd); // Definitely succeeds because "RecvRingBuff.ed" is only accessed in "UvRecvThread"
|
||||||
|
|
||||||
// Only increment cnt when the putting of new element is fully done.
|
// Only increment cnt when the putting of new element is fully done.
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
@ -698,6 +698,8 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.Rin
|
|||||||
} else if stoppingFromWalking {
|
} else if stoppingFromWalking {
|
||||||
thatPlayerInNextFrame.FramesToRecover = chConfig.InertiaFramesToRecover
|
thatPlayerInNextFrame.FramesToRecover = chConfig.InertiaFramesToRecover
|
||||||
} else {
|
} else {
|
||||||
|
// Updates CharacterState and thus the animation to make user see graphical feedback asap.
|
||||||
|
thatPlayerInNextFrame.CharacterState = ATK_CHARACTER_STATE_WALKING
|
||||||
thatPlayerInNextFrame.FramesToRecover = ((chConfig.InertiaFramesToRecover >> 1) + (chConfig.InertiaFramesToRecover >> 2))
|
thatPlayerInNextFrame.FramesToRecover = ((chConfig.InertiaFramesToRecover >> 1) + (chConfig.InertiaFramesToRecover >> 2))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user