@@ -2002,24 +2002,33 @@ internal open class BufferedChannel<E>(
2002
2002
* or `-1` if this channel does not contain buffered elements.
2003
2003
*/
2004
2004
private fun markAllEmptyCellsAsClosed (lastSegment : ChannelSegment <E >): Long {
2005
+ // Process the cells in reverse order, from right to left.
2005
2006
var segment = lastSegment
2006
2007
while (true ) {
2007
2008
for (index in SEGMENT_SIZE - 1 downTo 0 ) {
2008
- if (segment.id * SEGMENT_SIZE + index < receiversCounter) return - 1
2009
+ // Is this cell already covered by `receive()`?
2010
+ val globalIndex = segment.id * SEGMENT_SIZE + index
2011
+ if (globalIndex < receiversCounter) return - 1
2012
+ // Process the cell `segment[index]`.
2009
2013
cell_update@while (true ) {
2010
2014
val state = segment.getState(index)
2011
2015
when {
2016
+ // The cell is empty.
2012
2017
state == = null || state == = IN_BUFFER -> {
2018
+ // Inform a possibly upcoming sender that this channel is already closed.
2013
2019
if (segment.casState(index, state, CHANNEL_CLOSED )) {
2014
2020
segment.onSlotCleaned()
2015
2021
break @cell_update
2016
2022
}
2017
2023
}
2018
- state == = BUFFERED -> return segment.id * SEGMENT_SIZE + index
2024
+ // The cell stores a buffered element.
2025
+ state == = BUFFERED -> return globalIndex
2026
+ // Skip this cell if it is not empty and does not store a buffered element.
2019
2027
else -> break @cell_update
2020
2028
}
2021
2029
}
2022
2030
}
2031
+ // Process the next segment, finishing if the linked list ends.
2023
2032
segment = segment.prev ? : return - 1
2024
2033
}
2025
2034
}
0 commit comments