https://kotlinlang.org logo
#getting-started
Title
# getting-started
g

George

03/14/2022, 10:14 AM
Hi folks, Which is the proper way to enforce some piece of code to wait to be initialized something else first? I have something like this, but ofc it does not work.
Copy code
internal fun AtomicRef<MutableList<Pair<KClass<*>, KSerializer<*>>>>.getOrWait(): MutableList<Pair<KClass<*>, KSerializer<*>>> {
    while (this.value == emptyList<MutableList<Pair<KClass<*>, KSerializer<*>>>>())
        suspend {
            delay(10)
        }
    return this.value
}
Can anyone point any docs or articles on this subject? thanks in advance!
j

Joffrey

03/14/2022, 10:18 AM
What is this
AtomicRef<T>
type? It doesn't look like it's supposed to represent something that will be set in the future.
Deferred<T>
(if you're using coroutines) or other CompletableFuture-like types seem more appropriate for this, and then you would get this
await()
functionality for free
g

George

03/14/2022, 10:20 AM
Even if i need it to be thread-safe?. Although you are right this might what i need. (I will test it and let u know!) Thanks a lot !
a

Adrijan Rogan

03/14/2022, 10:27 AM
What about
Lazy
? It might fit your needs and is thread safe. I'm a bit confused about your use case, what do you actually want?
g

George

03/14/2022, 11:17 AM
Hmm the thing is i have mutalbe list
Copy code
internal val jsonSubclasses: Deferred<MutableList<Pair<KClass<*>, KSerializer<*>>>> =
    CompletableDeferred(mutableListOf())
and i add to it in the initialization many times
Copy code
internal suspend fun <T : Any> registerJsonSubclass(subclass: KClass<T>, serializer: KSerializer<T>) {
    jsonSubclasses.await().add(subclass to serializer)
}
So from what i see i think lazily doesnt suit me or correct me if im wrong. Though thanks for ur advice rogan! Is it ok for me to delay the initialization code like this?
Copy code
internal suspend fun Deferred<MutableList<Pair<KClass<*>, KSerializer<*>>>>.getOrWait(): MutableList<Pair<KClass<*>, KSerializer<*>>> {
    while (this.await() == emptyList<Pair<KClass<*>, KSerializer<*>>>())
        delay(10)
    return this.await()
}
Or i create many problems after this?
a

Adrijan Rogan

03/14/2022, 11:25 AM
Why do you need to wait (i.e. use deferred)? How do you use the
jsonSubclasses
variable?
g

George

03/14/2022, 11:41 AM
I might be going completely wrong about this but: Im trying to expose a var so anyone can register their classes for serialization e.g.
Copy code
internal val jsonPayloadModule: SerializersModule = SerializersModule {
    polymorphic(Any::class) {
        subclass(StringAsObjectSerializer)
        subclass(Data::class)
    }
}
My code is in a library and not on general code.
a

Adrijan Rogan

03/14/2022, 11:45 AM
OK, but why use delay/deferred/await then?
n

Nick Allen

03/14/2022, 9:39 PM
A standard
MutableList
is not thread-safe, no matter what contains it. If it's in a thread-safe container, then that thread-safety only applies to manipulating the container (like updating your
AtomicRef
to point at a new
MutableList
). If you want thread safe access to the list, then you need the list itself to be thread safe. What is calling
getOrWait
? The code setting up the SerializerModule? The code adding KSerializers? Why is it waiting? Just waiting for the list to be non-empty seems like a poor check if you want to wait it to be fully populated and there can be more than one item. Perhaps there is some extra infrastructure needed so that the initialization can be known for sure before the consumer of that initialized data even gets to it.
👍 1