bartvh
07/25/2019, 10:43 AMfun doStuffWith(res: SomeResource) {
// res will and MUST be released soon after this function returns
run {
// this is ok, run invokes the lambda immediately
res.doStuff()
}
foo {
// this will throw because I overlooked that foo invokes its lambda argument some time later, when res has been released
res.doStuff()
}
}
Do you think it would be possible in any way to make this usage a compile time error? Or to give a runtime exception earlier than in doStuff
.
Generally speaking, I'd want to prevent some object from being (accidentally) captured by a lambda that is not invoked immediately.
I don't think it's possible, especially not while still allowing the usage in run
, but I'm interested in your ideas.
Both SomeResource
and foo
are under my control.Marko Mitic
07/25/2019, 10:51 AMres.release()
res.doStuff()
bartvh
07/25/2019, 10:53 AMMarko Mitic
07/25/2019, 10:56 AMval res: SomeResource = ...
val job = async {
res.doStuff()
}
...
job.await()
res.release()
job.await()
wouldbartvh
07/25/2019, 10:57 AMCloseable
object that is `.use {}`d might be accessed after it has been closed.
but i'm not in the compiler writing business 😛Marko Mitic
07/25/2019, 11:02 AMbartvh
07/25/2019, 11:02 AMMarko Mitic
07/25/2019, 11:03 AMclass ReferenceCloser(closable: Closeable, referenceCount: Int = 1) {
private val count = AtomicInteger(referenceCount)
private var reference : Closeable? = closable
fun close() {
if (count.decrementAndGet() == 0) {
reference?.close()
reference = null
}
}
}
bartvh
07/25/2019, 11:10 AMMarko Mitic
07/25/2019, 11:12 AMfun doStuffWith(res: SomeResource) {
val closer = ReferenceCloser(res, 2)
foo {
res.doStuff()
closer.close()
}
doMoreStuffWith(res)
closer.close()
}
bartvh
07/25/2019, 11:12 AM