'Is there a thread-safe way to memoize a Kotlin Sequence?
I have a method which generates a sequence:
fun createFactorSequence(decimalMode: DecimalMode): Sequence<BigDecimal> {
var sign = BigDecimal.ZERO - BigDecimal.ONE
return createAllFactorialsSequence()
.filterIndexed { i, _ -> i % 2 != 0 }
.map { n ->
sign = -sign
sign * BigDecimal.ONE.divide(n, decimalMode)
}
}
Because the sequence will be the same between multiple invocations, it seems like it should be possible to cache it (I would have to key that by the decimal mode, in its current form, but there may be ways to remove the need for that).
I have seen some code out in the wild which attempts to implement a memoized sequence, recording the elements from the underlying sequence into a list so that the next invocation wouldn't need to recompute them.
They mostly work along these lines (I've simplified it to assume the sequence is infinite):
fun <T> memoizedSequence(slowSequence: Sequence<T>): Sequence<T> {
val slowIterator = slowSequence.iterator()
val cachedEntries = mutableListOf<T>()
return sequence {
var index = 0
while (true) {
// TODO: Not thread-safe!!
while (cachedEntries.size < index) {
cachedEntries.add(slowIterator.next())
}
yield(cachedEntries[index])
index++
}
}
}
The problem, as commented, is that this is not thread-safe. If two threads come through at the same time and each get an element from the iterator, there's no guarantee that the entries will end up in the list in the same order.
But I can't just use Java synchronization to get around it, because the library is multiplatform.
Is there a Kotlin way to do this?
I attempted to use Mutex (I'm not even sure whether adding a dependency on coroutines is going to be acceptable) but found that I'm not allowed to call Mutex.withLock from inside sequence {}.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
