uhe
02/16/2018, 9:49 AMsuspendAtomicCancellableCoroutine
and suspendCancellableCoroutine
?Jonathan
02/16/2018, 9:59 AMcont.resume()
, while the other may be cancelled even after calling cont.resume()
.uhe
02/16/2018, 12:30 PMJonathan
02/16/2018, 12:52 PMval atomicValue = AtomicInteger(0)
var value = 0
fun usage() {
// This doesn't ensure that the value printed is the one after increment
// Because another thread could have changed the value in between (it is not atomic)
++value
println(value)
// This ensure to print the correct value after increment (it is atomic)
println(atomicValue.incrementAndGet())
}
I think it is the same for coroutines cancellation
suspend fun atomicCancellableFct() =
suspendAtomicCancellableCoroutine<Unit> { it.resume(Unit) }
suspend fun cancellableFct() =
suspendCancellableCoroutine<Unit> { it.resume(Unit) }
suspend fun usage() {
// This call may throw a CancellationException, even if the actual content has been resumed
// This is because cancel may be called during the resume process
cancellableFct()
// This ensure that either
// * the content is resumed but doesn't throw any CancellationException
// * the content is NOT resumed and throw a CancellationException
// But never both, because it will be *atomic*
atomicCancellableFct()
}
And about how to choose, for me it is the same as choosing between Int
and AtomicInteger
.
I will always use non-atomic operations unless I am implementing a very specific case that does need to use atomicity.uhe
02/16/2018, 1:02 PMJonathan
02/16/2018, 1:07 PMlock()
of Mutex
. The cancellation of this function is atomic, and the reason is quite easy to understand I think. We need to be sure that either the function throw a CancellationException
OR a lock has been acquired, but not both. If the function would succeed to acquire a lock AND throw an exception, one could end up with deadlocks very difficult to debug.delay()
cancellation is not atomic, because in case of cancellation, we don't care if the delay already resumed or not.
Mutex.lock()
cancellation is atomic. Because in case of cancellation, if a lock has been acquired, we have to call Mutex.unlock()
to avoid deadlocks.suspendAtomicCancellableCoroutine
, otherwise, use suspendCancellableCoroutine
uhe
02/16/2018, 1:32 PMuli
02/16/2018, 7:04 PM