Could anyone explain why I get frozen collection m...
# kotlin-native
a
Could anyone explain why I get frozen collection mutation in this code? It is marked as ThreadLocal.
👀 1
b
Does @ThreadLocal work with companion objects?
Try putting @ThreadLocal over the HashMap instead
a
It should. And I am pretty sure that it worked before. I can't put it on a map inside singleton because it is restricted to top-level objects. I can move the cache to top level though.
r
It might help if you post the calling code and the error message
a
I am currently working on a different branch and just bypassed the cache. But how does it depend on the calling code?
r
because it's not clear just from what you've posted where the error is happening
a
It is happening on each call to invoke in all tests.
r
And is it definitely
defaultStridesCache
that's causing the error, as opposed to
shape
or something inside the
DefaultStrides
constructor?
You could try adding
init { defaultStridesCache.ensureNeverFrozen() }
and see if you get any more insight
a
Yes, the error is in the hashmap. Let me try to reproduce
Copy code
kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.collections.HashMap@a88e18
kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.collections.HashMap@a88e18
    at kfun:kotlin.Throwable#<init>(kotlin.String?;kotlin.Throwable?){} (0000000000414080)
    at kfun:kotlin.Throwable#<init>(kotlin.String?){} (0000000000414390)
    at kfun:kotlin.Exception#<init>(kotlin.String?){} (000000000040dc10)
    at kfun:kotlin.RuntimeException#<init>(kotlin.String?){} (000000000040dd40)
    at kfun:kotlin.native.concurrent.InvalidMutabilityException#<init>(kotlin.String){} (0000000000437710)
    at ThrowInvalidMutabilityException (0000000000438a60)
    at MutationCheck (00000000005d4a10)
    at kfun:kotlin.collections.HashMap.<set-length>#internal (0000000000420980)
    at kfun:kotlin.collections.HashMap#addKey(1:0){}<http://kotlin.Int|kotlin.Int> (0000000000424800)
    at kfun:kotlin.collections.HashMap#put(1:0;1:1){}1:1? (00000000004218c0)
    at kfun:space.kscience.kmath.nd.DefaultStrides.Companion#invoke(kotlin.IntArray){}space.kscience.kmath.nd.Strides (0000000000524d40)
r
ok yeah definitely try adding an
ensureNeverFrozen()
to see what's freezing it
a
It is not available in common, so I can't use it
r
You can expect/actual it and no-op on other platforms
💯 1
it's a useful tool to have lying around for troubleshooting
also in stately but you're probably not looking to pull in a library just to debug this
a
Yeah, I have a really tight schedule right now and don't have time to play with this. Moving cache to top level like
Copy code
@ThreadLocal
private val defaultStridesCache = HashMap<IntArray, Strides>()
solves the problem.
r
fair enough. Just watch out because if you're actually touching it from different threads they'll each have their own cache.
a
It is OK. I do not think it will be use in multi-thread environment and it is made only to save time a bit. Computation of strides is not that heavy, but it could be quite frequent. I've also tried to add lazy initialization to the cache and it does not help as well. Seems like a bug to me.