I’m looking for an elegant solution to this nasty ...
# coroutines
a
I’m looking for an elegant solution to this nasty hack - I need to read some data from hardware over an asynchronous interface, in response to an incoming HTTP request, which gets read into the member variable
hwData
. Rather than sleeping/spinning until the data becomes available, is there a coroutines-based solution to this?
Copy code
embeddedServer(Netty, 8080) {
            routing {
                get("/my_endpoint") {
                    triggerDataReadFromHardware()
                    while(hwData == null) { Thread.sleep(100) }
                    call.respond("${hwData!!}\n")
                    hwData = null
                }
            }
        }.start(wait = false)
e
does the hardware have a callback-based interface?
if so, it can be wrapped into a suspending function with suspendCoroutine or suspendCancellableCoroutine
a
sadly not - we write some data to a serial port and some time later we get some data back with an opcode, so we know what it is
s
But instead of sleep, i'd call delay. Sleep is blocking, delay is only suspending
Or have triggerDataReadFromHardware return a
Deferred<HwData>
... then you can do
call.respond("${triggerDataReadFromHardware().await()}\n")
a
Thanks - that feels like the right solution. Any good pointers with where to get started with implementation of a Deferred handler? (is “handler” even the right term - trying to get to the point of knowing what to google!)
e
if you have a thread dedicated to polling the hardware device... that would make sense
create a CompletableDeferred and register it with your poller; when it receives data it can call
.complete()
I'm curious what your plan is (if any) to handle concurrent access, though...
💯 1
s
Since you'd need to trigger the data-read, you may not need to poll continuously. Instead, you could get a deferred by calling
Copy code
Deferred<HwData> hwData = async(<http://Dispatchers.IO|Dispatchers.IO>) { hardware.poll(...) }
hardware.trigger(...)
return hwData
If you have to poll, you can use a rendezvous Channel instead, where the polling loop will block until data is received from the hardware and send that data onto the rendezvous channel. Then the async call can just do a hardwareChannel.receive() to get that data.