Hi, I have a class which contains a map of accumul...
# coroutines
j
Hi, I have a class which contains a map of accumulator values, like this:
Copy code
private val accumulators = mutableMapOf(
    "foo" to 0,
    "bar" to 0,
)
Then later on in an init block, I'm doing a heavy IO operation to count all the values. I'm walking a large file tree:
Copy code
init {
    MyScope(Dispatchers.IO).launch {
        // Walk file tree and accumulate values in map
    }
}
finally I have them declared in the class as delegates:
Copy code
val foo by accumulators
val bar by accumulators
How can I ensure that the
init
block runs before
foo
and
bar
are accessed? I'm using Swing, and when the UI loads, the user can click to display information. This operation inside
init
can take a few seconds, and it's possible the user requests the information during accumulation. Is there some sort of locking mechanism I can use so that when the user requests the info, it will wait in the backgorund and then show on the UI?
Overall I'm having trouble with figuring out the best practice to asynchronously create an instance of a class, and then to know exactly when that class will be ready to be accessed by the UI
u
makeing accumulators
Deferred<Map<String,Int>>
would do the trick. But then you have to await the value which needs a suspend function. As properties can not have supsend getters, you’d need to write a regular suspend fun:
Copy code
private val accumulators : Deferred<Map<String,Int>>

init {
  val completableDeferred = CompletableDeferred<Map<String,Int>>
  accumulators = completableDeferred
  val map = mutableMapOf(
    "foo" to 0,
    "bar" to 0,
  )
  MyScope(Dispatchers.IO).launch {
    // Walk file tree and accumulate values in map
    completableDeferred.compete(map)
  }
}

suspend fun foo() = accumulators.await().get("foo")
1. Disclaimer: Above code is untested (i.e. written in slack) 2. Good to know. Awaiting an already completed deferrable will return it’s value imediately
j
This is perfect! My example wasn't quite what I was doing.
foo
and
bar
are using a PropertyDelegateProvider which takes a
suspend
lamda as its delegate getValue funtion, and inside that lambda is where I get the map's value, so it ends up being exactly what I need.
Thanks for the input!
u
I don’t get it. Maybe I can learn here. I thought properties could not be suspend
j
Ah, I left out a detail. The properties are a simple wrapper class I have - not a primitive value - which has a suspend
getValue()
function.
u
ah, perfect
j
Would be nice syntactically to have suspend getters though!