refactor: replace synchronized with lock-free CAS in BleChunkAssembler
Use AtomicReference holding an immutable list with a compare-and-set loop, eliminating the synchronized block while maintaining thread safety. https://claude.ai/code/session_01KLRz7FJgWRtgCcZe3qD1VX
This commit is contained in:
+21
-15
@@ -20,37 +20,43 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.quartz.nipBEBle.protocol
|
package com.vitorpamplona.quartz.nipBEBle.protocol
|
||||||
|
|
||||||
|
import kotlin.concurrent.atomics.AtomicReference
|
||||||
|
import kotlin.concurrent.atomics.ExperimentalAtomicApi
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accumulates incoming BLE chunks for a single message and reassembles
|
* Accumulates incoming BLE chunks for a single message and reassembles
|
||||||
* them once all chunks have arrived.
|
* them once all chunks have arrived.
|
||||||
*
|
*
|
||||||
* Thread-safe: all access to internal state is synchronized.
|
* Thread-safe: uses a lock-free compare-and-set loop over an immutable list.
|
||||||
*/
|
*/
|
||||||
|
@OptIn(ExperimentalAtomicApi::class)
|
||||||
class BleChunkAssembler {
|
class BleChunkAssembler {
|
||||||
private val lock = Any()
|
private val receivedChunks = AtomicReference(emptyList<ByteArray>())
|
||||||
private val receivedChunks = mutableListOf<ByteArray>()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a received chunk. If this completes the message, returns the
|
* Adds a received chunk. If this completes the message, returns the
|
||||||
* reassembled JSON string. Otherwise returns null.
|
* reassembled JSON string. Otherwise returns null.
|
||||||
*/
|
*/
|
||||||
fun addChunk(chunk: ByteArray): String? =
|
fun addChunk(chunk: ByteArray): String? {
|
||||||
synchronized(lock) {
|
while (true) {
|
||||||
receivedChunks.add(chunk)
|
val current = receivedChunks.load()
|
||||||
if (BleMessageChunker.isComplete(receivedChunks)) {
|
val updated = current + chunk
|
||||||
val message = BleMessageChunker.joinChunks(receivedChunks.toTypedArray())
|
if (BleMessageChunker.isComplete(updated)) {
|
||||||
receivedChunks.clear()
|
if (receivedChunks.compareAndSet(current, emptyList())) {
|
||||||
message
|
return BleMessageChunker.joinChunks(updated.toTypedArray())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
null
|
if (receivedChunks.compareAndSet(current, updated)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Discards any partially received chunks.
|
* Discards any partially received chunks.
|
||||||
*/
|
*/
|
||||||
fun reset() =
|
fun reset() {
|
||||||
synchronized(lock) {
|
receivedChunks.store(emptyList())
|
||||||
receivedChunks.clear()
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user