Use snapshots for sending order to improve send efficiency.

This commit is contained in:
Koen J 2025-05-16 12:34:48 +02:00
commit 94965cf3ba

View file

@ -17,6 +17,8 @@ interface IAuthorizable {
class SyncSession : IAuthorizable { class SyncSession : IAuthorizable {
private val _channels: MutableList<IChannel> = mutableListOf() private val _channels: MutableList<IChannel> = mutableListOf()
@Volatile
private var _snapshot: Array<IChannel> = emptyArray()
private var _authorized: Boolean = false private var _authorized: Boolean = false
private var _remoteAuthorized: Boolean = false private var _remoteAuthorized: Boolean = false
private val _onAuthorized: (session: SyncSession, isNewlyAuthorized: Boolean, isNewSession: Boolean) -> Unit private val _onAuthorized: (session: SyncSession, isNewlyAuthorized: Boolean, isNewSession: Boolean) -> Unit
@ -83,6 +85,8 @@ class SyncSession : IAuthorizable {
synchronized(_channels) { synchronized(_channels) {
_channels.add(channel) _channels.add(channel)
_channels.sortBy { it.linkType.ordinal }
_snapshot = _channels.toTypedArray()
connected = _channels.isNotEmpty() connected = _channels.isNotEmpty()
} }
@ -124,15 +128,20 @@ class SyncSession : IAuthorizable {
fun removeChannel(channel: IChannel) { fun removeChannel(channel: IChannel) {
synchronized(_channels) { synchronized(_channels) {
_channels.remove(channel) _channels.remove(channel)
_snapshot = _channels.toTypedArray()
connected = _channels.isNotEmpty() connected = _channels.isNotEmpty()
} }
} }
fun close() { fun close() {
synchronized(_channels) { val toClose = synchronized(_channels) {
_channels.toTypedArray() val arr = _channels.toTypedArray()
}.forEach { it.close() } _channels.clear()
_snapshot = emptyArray()
connected = false
arr
}
toClose.forEach { it.close() }
_onClose(this) _onClose(this)
} }
@ -209,13 +218,12 @@ class SyncSession : IAuthorizable {
fun send(opcode: UByte, subOpcode: UByte, data: ByteBuffer? = null, contentEncoding: ContentEncoding? = null) { fun send(opcode: UByte, subOpcode: UByte, data: ByteBuffer? = null, contentEncoding: ContentEncoding? = null) {
ensureNotMainThread() ensureNotMainThread()
val channels = synchronized(_channels) { _channels.sortedBy { it.linkType.ordinal }.toList() } val channels = _snapshot
if (channels.isEmpty()) { if (channels.isEmpty()) {
//TODO: Should this throw? Logger.v(TAG, "Packet was not sent … no connected sockets")
Logger.v(TAG, "Packet was not sent (opcode = $opcode, subOpcode = $subOpcode) due to no connected sockets")
return return
} }
var sent = false var sent = false
for (channel in channels) { for (channel in channels) {
try { try {