-
Notifications
You must be signed in to change notification settings - Fork 851
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Logic refax: new rules for the receiver buffer and TSBPD #2527
base: master
Are you sure you want to change the base?
Logic refax: new rules for the receiver buffer and TSBPD #2527
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2527 +/- ##
==========================================
- Coverage 65.08% 0.00% -65.09%
==========================================
Files 101 101
Lines 17655 19849 +2194
==========================================
- Hits 11490 0 -11490
- Misses 6165 19849 +13684 ☔ View full report in Codecov by Sentry. |
srtcore/core.h
Outdated
// This function is to return the packet's play time (time when | ||
// it is submitted to the reading application) of the given packet. | ||
// This grp passed here by void* because in the current imp it's | ||
// unused and shall not be used in case when ENABLE_BONDING=0. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// This function is to return the packet's play time (time when | |
// it is submitted to the reading application) of the given packet. | |
// This grp passed here by void* because in the current imp it's | |
// unused and shall not be used in case when ENABLE_BONDING=0. | |
/// This function is to return the packet's play time (time when | |
/// it is submitted to the reading application) of the given packet. | |
/// This grp passed here by void* because in the current imp it's | |
/// unused and shall not be used in case when ENABLE_BONDING=0. |
srtcore/core.cpp
Outdated
THREAD_PAUSED(); | ||
tsbpd_cc.wait_until(tsNextDelivery); | ||
bWakeupOnSignal = tsbpd_cc.wait_until(tsNextDelivery); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bWakeupOnSignal = tsbpd_cc.wait_until(tsNextDelivery); | |
bWokenupOnSignal = tsbpd_cc.wait_until(tsNextDelivery); |
srtcore/core.cpp
Outdated
THREAD_PAUSED(); | ||
tsbpd_cc.wait(); | ||
THREAD_RESUMED(); | ||
} | ||
|
||
HLOGC(tslog.Debug, log << self->CONID() << "tsbpd: WAKE UP!!!"); | ||
HLOGC(tslog.Debug, log << self->CONID() << "tsbpd: WAKE UP [" << (bWakeupOnSignal? "signal" : "timeout") << "]!!! - " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HLOGC(tslog.Debug, log << self->CONID() << "tsbpd: WAKE UP [" << (bWakeupOnSignal? "signal" : "timeout") << "]!!! - " | |
HLOGC(tslog.Debug, log << self->CONID() << "tsbpd: WAKE UP [" << (bWokenupOnSignal? "signal" : "timeout") << "]!!! - " |
srtcore/utilities.h
Outdated
/* | ||
const T& operator[](int index) const | ||
{ | ||
if (index < 0 || static_cast<size_t>(index) >= m_size) | ||
throw_invalid_index(index); | ||
|
||
return m_entries[index]; | ||
} | ||
|
||
T& operator[](int index) | ||
{ | ||
if (index < 0 || static_cast<size_t>(index) >= m_size) | ||
throw_invalid_index(index); | ||
|
||
return m_entries[index]; | ||
} | ||
*/ |
Check notice
Code scanning / CodeQL
Commented-out code Note
srtcore/buffer_rcv.cpp
Outdated
|
||
const int pos = (m_iStartPos + offset) % m_szSize; | ||
//const CPos newpktpos = m_iStartPos + offset; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//const CPos newpktpos = m_iStartPos + offset; |
srtcore/buffer_rcv.cpp
Outdated
std::pair<int, int> CRcvBuffer::dropUpTo(int32_t seqno) | ||
{ | ||
IF_RCVBUF_DEBUG(ScopedLog scoped_log); | ||
IF_RCVBUF_DEBUG(scoped_log.ss << "CRcvBuffer::dropUpTo: seqno " << seqno << " m_iStartSeqNo " << m_iStartSeqNo); | ||
|
||
int len = CSeqNo::seqoff(m_iStartSeqNo, seqno); | ||
COff len = COff(CSeqNo(seqno) - m_iStartSeqNo); | ||
//int len = CSeqNo::seqoff(m_iStartSeqNo, seqno); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//int len = CSeqNo::seqoff(m_iStartSeqNo, seqno); |
srtcore/buffer_rcv.cpp
Outdated
if (m_iEndOff == m_iMaxPosOff) | ||
return SRT_SEQNO_NONE; | ||
|
||
//int offset = CSeqNo::seqoff(m_iStartSeqNo, fromseq); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//int offset = CSeqNo::seqoff(m_iStartSeqNo, fromseq); |
srtcore/buffer_rcv.h
Outdated
return true; | ||
|
||
const CPos iLastPos = CPos((iStartPos VALUE + iMaxPosOff VALUE) % int(iSize)); | ||
//const CPos iLastPos = iStartPos + iMaxPosOff; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//const CPos iLastPos = iStartPos + iMaxPosOff; |
CMakeLists.txt
Outdated
@@ -1527,7 +1527,7 @@ if (ENABLE_UNITTESTS AND ENABLE_CXX11) | |||
#set_tests_properties(test-srt PROPERTIES RUN_SERIAL TRUE) | |||
else() | |||
set_tests_properties(${tests_srt} PROPERTIES RUN_SERIAL TRUE) | |||
gtest_discover_tests(test-srt) | |||
#gtest_discover_tests(test-srt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This excludes unit testing from GitHub CI jobs and makes the CodeCov gate fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is CodeCov using the only possible default configuration, or it can be done with enabled on demand?
Here I can withdraw this change, but enabling these tests on demand (and not by default) is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I fixed this by adding an option to disable test discovery.
This changes largely the logics of the buffer and TSBPD. This change was necessary for supporting the group common buffer reception, but it should as well improve the TSBPD performance and efficiency.
The original receiver buffer in the cooperation with TSBPD was still running on the original UDT's idea of passing the packets at the ACK time, and until the ACK was done, they were not available, even if their retrieval would be theoretically possible. This design changes the TSBPD to work directly on the buffer, therefore there have been consolidated less events to trigger the TSBPD wakeup and recheck. There are actually the following situations:
m_bTsbPdNeedsWakeup
field).[0]
cell as ready to play and expects that the API call retrieve it: the API call should wake it up after the packet has been retrieved (this is the old way and remains the same here).[0]
cell. This sleep is not interrupted in any situation.Note that in the case of forever sleeping, there's no way to distinguish the reason of "still ready to read" and "nothing to wait up to" situations - might be that this can be improved, so - for example - if there is at least one packet "in the past" (not necessarily at cell
[0]
) then TSBPD should NOT be woken up in the event of incoming packet, regardless of its position.Anyway, the change for triggering TSBPD is that:
m_bTsbPdNeedsWakeup
flag is set.Beside the taking out of the TSBPD triggering in the ACK handler, there's also one more change added: the ACK number to be sent back to the sender is extracted exclusively from the receiver buffer, and no longer from the loss list and internal fields. This is because the receiver buffer was added a functionality to be able to check this thing quickly. This is also a more reliable source of information and not prone to any race conditions.
Changes in the receiver buffer:
Introduced are terms of "initial contiguous region" (ICR) and "first gap". The first term existed in the old receiver buffer and it's the series of valid packets starting with the first cell up to the "first gap", that is, the series starting from at least one empty cell followed by a valid packet. None of them exist in an empty buffer. The "first gap" also may not exist if all packets from the first cell up to the one pointed by
m_iMaxPosOff
are valid. If the first gap starts with the first cell, this is also an "initial gap".Two new fields were added, which are defined as offset towards
m_iStartPos
:m_iEndOff
andm_iDropOff
:m_iEndOff
: marks the past-the-end of the initial contiguous region. If this region is empty,m_iEndOff
is 0. This field always points to an empty cell.m_iDropOff
: marks the position of the first valid packet following the first gap. This position is always earlier than the one pointed bym_iMaxPosOff
, but later thanm_iEndOff
. If no such packet exists, this field has value 0. Note that there couldn't be a drop at the 0 position, at worst it can bem_iEndOff
equal to 0 (which means that ICR is empty) and thenm_iDropOff
equal to 1, if the cell at[1]
contains a valid packet.These positions are being updated in case of various events that may influence their positions, so for example:
m_iEndOff
in stream mode). This shifts the initial position by 1, and may potentially reach up to m_iEndOff, but this may only happen if the buffer becomes empty. Otherwise m_iEndOff and m_iDropOff are far in forward, so nothing to change here.m_iEndOff
withm_iDropOff
== 0. Onlym_iEndOff
is increased by 1.m_iEndOff
with existing "first gap". If the next position towardsm_iEndOff
is busy, ride with m_iEndOff to find a new end of initial contiguous region, and then ride with m_iDropOff, from this position on, to find the after-gap position, both up to m_iMaxPosOff.m_iEndOff
and afterm_iDropOff
: nothing to be updatedm_iEndOff
, but beforem_iDropOff
: find the first valid packet sincem_iEndOff
and set its position tom_iDropOff
. NOTIFY TIME of the delivery for the new drop position.m_iStartPos
) to the position ofm_iDropOff
, and then the procedure of finding the end of the contiguous region and the prospective end of first gap starts anew (updateGapInfo
).m_iEndOff
, andm_iMaxPosOff
is equal to it. In this case only them_iEndOff
is shifted by 1.m_iDropOff
is always set to 0. This field is not in use in message mode (it points to a packet, not to a beginning of the message) and the position pointed by it may be taken out the packet, which makes it point to an empty cell.Note that there are many mutually-exclusive conditions here, for example:
m_iEndOff
is the earliest position where insertion may happen.m_iDropOff
never precedesm_iEndOff
, unless it's 0, and if it's not 0, it always points to a valid packet.m_iDropOff
, and if this happens, it was pointing to a valid packet. After thatm_iStartPos
is set to that position and searching for candidates to set tom_iEndOff
begins with the next packet.There are therefore changed the procedures of:
m_iDropOff
. Dropping the whole message doesn't rely on it as in the message mode dropping is only for the whole message and results either in an empty buffer or resets the initial contiguous region and hence the other flags.