I am trying to define a multiplatform ConcurrentHa...
# multiplatform
m
I am trying to define a multiplatform ConcurrentHashMap with the following code: Common:
Copy code
internal expect class ConcurrentMutableMap<K, V>() : MutableMap<K, V>
iOS:
Copy code
internal actual class ConcurrentMutableMap<K, V> : MutableMap<K, V> {
    override fun put(key: K, value: V)...
}
Android/JVM:
Copy code
internal actual class ConcurrentMutableMap<K, V>(
    map: ConcurrentHashMap<K, V>
) : MutableMap<K, V> by map {
    actual constructor() : this(ConcurrentHashMap())
}
This does not show any errors inside of IntelliJ, but when compiling with Gradle it fails with the following error:
Copy code
commonMain/kotlin/PlatformApiProviders.kt:15:17 Class 'ConcurrentMutableMap' is not abstract and does not implement abstract member 'put'.
Just as a test, I tried manually adding the missing function inside of my common definition (as well as adding "actual" to the function definition in my iOS code):
Copy code
internal expect class ConcurrentMutableMap<K, V>() : MutableMap<K, V> {
    override fun put(key: K, value: V): V?
}
And this fixes the issue, but now it just complains that "remove" is not implemented instead. My question now is if there is a way to fix this issue without just listing every function defined in
MutableMap
again in my common code.
a
Maybe there is a library already doing this?
m
As in it that this issue could be caused by a library conflict, or that I could use a library instead of implementing it myself?
a
Yes no 2
m
It's interesting that it complains about the one in the
commonMain
source set. But a typealias might be better.
public actual typealias ConcurrentMutableMap = ConcurrentHashMap
a
A quick google search revealed touchlab concurent collections
Maybe its of use for you
m
I tried the typealias, but the problem is that ConcurrentHashMap does not satisfy the empty constructor requirement.
m
Maybe make the constructor a stand alone function instead of an actual constructor. Or something like
concurrentMutableMapOf
.
m
> A quick google search revealed touchlab concurent collections I tried that one, but unfortunately it is completely broken since its concurrent map does not actually allow concurrent modifications. https://github.com/touchlab/Stately/issues/105
👍 1
That would be my final option, but I hoped I would just be able to use a class. While trying things in my code just now I realised that Ktor exposes a concurrent map too, which does seem to work fine for me. Judging by the comment on the class saying "Ktor concurrent map implementation. Please do not use it.", it would probably be a bad idea to depend on it?
Right sorry, I misremembered. I was unable to use the typealias because
Copy code
internal actual typealias ConcurrentMutableMap<K, V> = ConcurrentHashMap<K, V>
causes the following issue:
Copy code
'actual typealias ConcurrentMutableMap<K, V> = ConcurrentHashMap<K, V>' has no corresponding members for expected class members:

    expect val keys: MutableSet<K>

    The following declaration is incompatible because return type is different:
        val keys: ConcurrentHashMap.KeySetView<K!, V!>
m
Yeah, would be hesitant to rely on a class with that comment. I think what you wrote should work, and I would probably file a bug about it. But I think
expect fun ConcurrentMutableMap<K, V>(): MutableMap<K, V>
would be a reasonable solution. I guess the main issue is that it means you cannot take a
ConcurrentMutableMap
as an argument to enforce concurrency.
expect
classes are still considered experimental versus expect functions.
m
Hmm, I see. Unfortunately the issue is that even if I did get the type alias to work, it still causes the same issue about
put
being missing on top of the incompatible definition for
keys
field.
It looks stupid, but this code here actually fixes the issue for some reason:
It just requires me to add
actual
to all of the implementations on iOS. Of course I am not crazy about using a fix like that...
Weird part that I also forgot to mention: The compilation issue only occurs when compiling the Android artifacts. iOS is completely fine. Makes it even more mysterious to me.