https://kotlinlang.org logo
#coroutines
Title
# coroutines
l

louiscad

12/12/2017, 9:19 AM
Hi, is there a way to throw an exception on the next channel suspended
receive()
without closing the channel, thus allowing subsequent attempts to get a value from the channel? I assume
Channel
is not the right choice, but after reading the whole kotlinx.coroutines README, I did not find what I'm looking for.
e

elizarov

12/12/2017, 9:43 AM
So, what exactly you are trying to achieve? Maybe you want just to cancel one specific receive operation? Then just cancel the job this specific receive is a part of (it will not consume a value from a channel if it was cancelled)
l

louiscad

12/12/2017, 10:07 AM
I'm trying to make the Bluetooth Low Energy usable with coroutines. The issue with the job cancellation is that I don't know how to do it, especially since there may be multiple waiting jobs. Here's a gist with my draft. I think you'll understand what I want to do: https://gist.github.com/LouisCAD/88d06da6ae1caf04acbf6cd4fc1d5cac
e

elizarov

12/12/2017, 10:09 AM
But why (if even) this cancellation problem arises? In what case you’d like to throw an exception on a suspended
receive
without closing a channel?
l

louiscad

12/12/2017, 10:13 AM
You can see from line 71 the possible values of
status
received in the god callback methods (constants starting with
GATT_
). Note that there's also a famous 133 error value that is not documented, and possibly other unexpected values, that may just be sign of a random failure that may not render the connection unusable or closed though: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/bluetooth/BluetoothGatt.java#71
e

elizarov

12/12/2017, 10:19 AM
Instead of sending
E
into the channel I’d simply introduce
data class ValueStatus(val value: E, val status: Int
) and send it instead to the channel. Then let
receive
see what status was received and act accordingly (either wait for more or bail out)
👍🏽 1
l

louiscad

12/12/2017, 10:24 AM
I thought about this, or using a sealed class, so I think I'll follow your recommendation. However, couldn't a Channel that can throw only on the next
receive()
be added so there's no need to "box" what needs to be sent when everything goes with success? I mean, there's probably more use cases that could benefit from this, don't you think?
e

elizarov

12/12/2017, 10:42 AM
That is a very domain-specific behavior that can be easily modeled with an extra data or sealed class, hence I don’t see any need to support it “out of the box”.
Moreover, in you’re case you’d want to create exception in the corresponding business method (after analysis of status) instead of creating it inside your callback, so that exception’s stack track trace is more relevant. And for transient error (when you need to wait more) it is easier not to have exception at all. Your custom class will model this better
l

louiscad

12/12/2017, 10:53 AM
Out of the box support for this could be helpful for BluetoothGatt usage on other platforms such as iOS and embedded systems too, and would avoid unnecessary allocation on success. In this case, the stacktrace isn't likely to help as long as the self-made exception reveals the underlying non successful status and is thrown in the proper coroutine. I mean, the errors that can arise are not expected to come from programmer error, but from connection issues, or not allowed read/write operations. But if BluetoothGatt is the only use case that may benefit from this workaround-able thing, I agree that it may not be worth implementing it. Thanks a lot for your help, I'm getting close to a BLE GATT coroutines API!
3 Views