Refactoring mutexes and evet around CSndUList #2045
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
A rework of PRs #1814 and #1844. Closes #1814, #1844.
This PR introduces three changes divided into three commits.
Moved mutexes from
CSndQueue
As noted in #1814, the
CSndQueue
has two members:m_WindowLock
mutex andm_WindowCond
CV. Pointers to those are given toCSndUList
to signal an event of the list transitioning from an empty to a non-empty state.Here is how it looks:
CSndUList
- list (heap) ofCUDT
sockets to send data packets.m_ListLock
- locksCSndUList
modifications.update
,pop
,remove
,getNextProcTime
.m_pWindowLock
- pointer to mutex owned byCSndQueue
, only used together with the CV to signal there was a new entry added if it was empty.m_pWindowCond
- a pointer to a CV owned byCSndQueue
.CSndQueue
- a class that ownsCSndUList
.m_WindowLock
m_WindowCond
- CV used to wait forCSndUList
to become non-empty. Also signalled in the destructor to unblock the worker thread.This PR moves
m_WindowLock
andm_WindowCond
toCSndUList, and combines
m_ListLockwith
m_WindowLock.
CSndUList` gains two new functions:CSndUList::pop(..)
logic simplifiedThe
CSndUList::pop(..)
function does several things:CUDT::packData(..)
).Performing these three steps overcomplicates the function and also holds a lock on the list while a data packet is prepared (which might take some time). Changes in PR #1844 were unlocking the
m_ListLock
beforepackData
and locking back afterwards. But it also allows a list to be changed by some other thread, thus inserting back to the list must be done combined with checking theCUDT
is not already in the list. That's whatCSndUList::update(..)
function does.This PR leaves only no. 1 in the
CSndUList::pop(..)
function. No. 2 and 3 are moved to theCSndQueue::worker(..)
function.CSndUList::update(..)
if earlier timeNow with a target processing time provided as an argument, reschedule only if the provided time is less (earlier) than the currently scheduled time. It allows to not touch the heap if already scheduled.
TODO
Performance Considerations
Previously
CSndUList::pop(..)
was taking a socket from the heap, preparing a data packet to send, and rescheduling the sending. On one hand, having these three operations under the heap lock was ensuring that a socket was removed from the heap (list), and rescheduling does not need to check if the socket is in the heap.On another hand, packing a data packet was blocking further work with the socket list (heap), e.g. adding another socket to the heap. However, there is only one sending worker thread, which can't take the next socket until data packet preparation is finished.
With the proposed changes a socket is extracted from the heap, a data packet is formed, and the socket is rescheduled if needed. Rescheduling is done with an assumption that socket might again exist in the heap, so an additional check is performed.
This check does not seem to provide any significant impact on the performance, however, it might be a point of further optimizations in the future. The updated logic of the
CSndUList::update(..)
function enables some further optimisations, required for #1910.