I have the following class:
class SdkWrapper(private val sdk: Sdk) {
private var inited = false
suspend fun doSomething() = withContext(Dispatchers.IO) {
if (inited.not()) init()
useSdk()
}
private fun init() {
// takes a long time
sdk.init()
inited = true
}
// has to be done asynchronously
// sdk.init() has to have been called before using this
private fun useSdk() {
}
}
class Sdk {
// must only be done once
fun init() {}
}
Before I can do useSdk()
, I must call sdk.init()
, but sdk.init()
must only be called once, not more.
With my current solution, if doSomething
is called twice quickly (the second time happening while sdk.init()
still running), I would call sdk.init()
twice, because inited: Boolean
is still false
.
If I move the assignment of inited
up like:
private fun init() {
inited = true
sdk.init()
}
and doSomething()
is called twice rapidly, the second call would use the sdk before its' init()
has been done.
I tried to solve this with:
suspend fun doSomething() = synchronized(this){
withContext(Dispatchers.IO) {
if (inited.not()) init()
useSdk()
}
}
but receive an error in IntelliJ:
the withContext suspension point is inside a critical section
I assume that synchronized
wouldn't work here anyway, because we move off the main thread and doSomething()
is completed while the withContext
block is still running?
How can I solve the problem at hand which basically is: doSomething()
should only run once at a time?