https://kotlinlang.org logo
Join the conversationJoin Slack
Channels
100daysofcode
100daysofkotlin
100daysofkotlin-2021
advent-of-code
aem
ai
alexa
algeria
algolialibraries
amsterdam
android
android-architecture
android-databinding
android-studio
androidgithubprojects
androidthings
androidx
androidx-xprocessing
anime
anko
announcements
apollo-kotlin
appintro
arabic
argentina
arkenv
arksemdevteam
armenia
arrow
arrow-contributors
arrow-meta
ass
atlanta
atm17
atrium
austin
australia
austria
awesome-kotlin
ballast
bangladesh
barcelona
bayarea
bazel
beepiz-libraries
belgium
berlin
big-data
books
boston
brazil
brikk
budapest
build
build-tools
bulgaria
bydgoszcz
cambodia
canada
carrat
carrat-dev
carrat-feed
chicago
chile
china
chucker
cincinnati-user-group
cli
clikt
cloudfoundry
cn
cobalt
code-coverage
codeforces
codemash-precompiler
codereview
codingame
codingconventions
coimbatore
collaborations
colombia
colorado
communities
competitive-programming
competitivecoding
compiler
compose
compose-android
compose-desktop
compose-hiring
compose-ios
compose-mp
compose-ui-showcase
compose-wear
compose-web
connect-audit-events
corda
cork
coroutines
couchbase
coursera
croatia
cryptography
cscenter-course-2016
cucumber-bdd
cyprus
czech
dagger
data2viz
databinding
datascience
dckotlin
debugging
decompose
decouple
denmark
deprecated
detekt
detekt-hint
dev-core
dfw
docs-revamped
dokka
domain-driven-design
doodle
dsl
dublin
dutch
eap
eclipse
ecuador
edinburgh
education
effective-kotlin
effectivekotlin
emacs
embedded-kotlin
estatik
event21-community-content
events
exposed
failgood
fb-internal-demo
feed
firebase
flow
fluid-libraries
forkhandles
forum
fosdem
fp-in-kotlin
framework-elide
freenode
french
fritz2
fuchsia
functional
funktionale
gamedev
ge-kotlin
general-advice
georgia
geospatial
german-lang
getting-started
github-workflows-kt
glance
godot-kotlin
google-io
gradle
graphic
graphkool
graphql
graphql-kotlin
graviton-browser
greece
grpc
gsoc
gui
hackathons
hacktoberfest
hamburg
hamkrest
helios
helsinki
hexagon
hibernate
hikari-cp
hire-me
hiring
hongkong
hoplite
http4k
hungary
hyderabad
image-processing
india
indonesia
inkremental
intellij
intellij-plugins
intellij-tricks
internships
introduce-yourself
io
ios
iran
israel
istanbulcoders
italian
jackson-kotlin
jadx
japanese
jasync-sql
java-to-kotlin-refactoring
javadevelopers
javafx
javalin
javascript
jdbi
jhipster-kotlin
jobsworldwide
jpa
jshdq
juul-libraries
jvm-ir-backend-feedback
jxadapter
k2-early-adopters
kaal
kafka
kakao
kalasim
kapt
karachi
karg
karlsruhe
kash_shell
kaskade
kbuild
kdbc
kgen-doc-tools
kgraphql
kinta
klaxon
klock
kloudformation
kmdc
kmm-español
kmongo
knbt
knote
koalaql
koans
kobalt
kobweb
kodein
kodex
kohesive
koin
koin-dev
komapper
kondor-json
kong
kontent
kontributors
korau
korean
korge
korim
korio
korlibs
korte
kotest
kotest-contributors
kotless
kotlick
kotlin-asia
kotlin-beam
kotlin-by-example
kotlin-csv
kotlin-data-storage
kotlin-foundation
kotlin-fuel
kotlin-in-action
kotlin-inject
kotlin-latam
kotlin-logging
kotlin-multiplatform-contest
kotlin-mumbai
kotlin-native
kotlin-pakistan
kotlin-plugin
kotlin-pune
kotlin-roadmap
kotlin-samples
kotlin-sap
kotlin-serbia
kotlin-spark
kotlin-szeged
kotlin-website
kotlinacademy
kotlinbot
kotlinconf
kotlindl
kotlinforbeginners
kotlingforbeginners
kotlinlondon
kotlinmad
kotlinprogrammers
kotlinsu
kotlintest
kotlintest-devs
kotlintlv
kotlinultimatechallenge
kotlinx-datetime
kotlinx-files
kotlinx-html
kotrix
kotson
kovenant
kprompt
kraph
krawler
kroto-plus
ksp
ktcc
ktfmt
ktlint
ktor
ktp
kubed
kug-leads
kug-torino
kvision
kweb
lambdaworld_cadiz
lanark
language-evolution
language-proposals
latvia
leakcanary
leedskotlinusergroup
lets-have-fun
libgdx
libkgd
library-development
linkeddata
lithuania
london
losangeles
lottie
love
lychee
macedonia
machinelearningbawas
madrid
malaysia
mathematics
meetkotlin
memes
meta
metro-detroit
mexico
miami
micronaut
minnesota
minutest
mirror
mockk
moko
moldova
monsterpuzzle
montreal
moonbean
morocco
motionlayout
mpapt
mu
multiplatform
mumbai
munich
mvikotlin
mvrx
myndocs-oauth2-server
naming
navigation-architecture-component
nepal
new-mexico
new-zealand
newname
nigeria
nodejs
norway
npm-publish
nyc
oceania
ohio-kotlin-users
oldenburg
oolong
opensource
orbit-mvi
osgi
otpisani
package-search
pakistan
panamá
pattern-matching
pbandk
pdx
peru
philippines
phoenix
pinoy
pocketgitclient
polish
popkorn
portugal
practical-functional-programming
proguard
prozis-android-backup
pyhsikal
python
python-contributors
quasar
random
re
react
reaktive
realm
realworldkotlin
reductor
reduks
redux
redux-kotlin
refactoring-to-kotlin
reflect
refreshversions
reports
result
rethink
revolver
rhein-main
rocksdb
romania
room
rpi-pico
rsocket
russian
russian_feed
russian-kotlinasfirst
rx
rxjava
san-diego
science
scotland
scrcast
scrimage
script
scripting
seattle
serialization
server
sg-user-group
singapore
skia-wasm-interop-temp
skrape-it
slovak
snake
sofl-user-group
southafrica
spacemacs
spain
spanish
speaking
spek
spin
splitties
spotify-mobius
spring
spring-security
squarelibraries
stackoverflow
stacks
stayhungrystayfoolish
stdlib
stlouis
strife-discord-lib
strikt
students
stuttgart
sudan
swagger-gradle-codegen
swarm
sweden
swing
swiss-user-group
switzerland
talking-kotlin
tallinn
tampa
teamcity
tegal
tempe
tensorflow
terminal
test
testing
testtestest
texas
tgbotapi
thailand
tornadofx
touchlab-tools
training
tricity-kotlin-user-group
trójmiasto
truth
tunisia
turkey
turkiye
twitter-feed
uae
udacityindia
uk
ukrainian
uniflow
unkonf
uruguay
utah
uuid
vancouver
vankotlin
vertx
videos
vienna
vietnam
vim
vkug
vuejs
web-mpp
webassembly
webrtc
wimix_sentry
wwdc
zircon
Powered by Linen
coroutines
  • z

    zeugederunity

    06/30/2021, 1:07 PM
    Hello everyone, when calling ReceiveChannel<T>::receiveCatching i get an object of type ChannelResult<ChannelResult<T>> back. But when i call ReceiveChannel<T>::receive i get an object of type T. Is this a bug or did i miss something in the API? Thanks in advance!
    d
    e
    j
    • 4
    • 8
  • d

    Daniele Segato

    06/30/2021, 10:59 PM
    Is there any performance or concurrency difference in using a MutableSharedFlow (with replay 1, buffer 1 and drop oldest) over a MutableStateFlow?
    MutableSharedFlow<Something?>(
        replay = 1,
        extraBufferCapacity = 1,
        onBufferOverflow = BufferOverflow.DROP_OLDEST
    )
    vs
    MutableStateFlow<Something?>(null)
    d
    n
    • 3
    • 7
  • n

    napperley

    07/01/2021, 2:32 AM
    Does the GlobalScope.launch function not work with the linuxX64 target? Confusing error messages keep on appearing, eg:
    kotlin.IllegalStateException: There is no event loop. Use runBlocking { ... } to start one.
        at kfun:kotlinx.coroutines.takeEventLoop#internal (0x312759)
        at kfun:kotlinx.coroutines.DefaultExecutor#dispatch(kotlin.coroutines.CoroutineContext;kotlinx.coroutines.Runnable){} (0x312570)
        at kfun:kotlinx.coroutines.internal#resumeCancellableWith@kotlin.coroutines.Continuation<0:0>(kotlin.Result<0:0>;kotlin.Function1<kotlin.Throwable,kotlin.Unit>?){0§<kotlin.Any?>} (0x30d572)
        at kfun:kotlinx.coroutines.intrinsics#startCoroutineCancellable$default@kotlin.coroutines.SuspendFunction1<0:0,0:1>(0:0;kotlin.coroutines.Continuation<0:1>;kotlin.Function1<kotlin.Throwable,kotlin.Unit>?;kotlin.Int){0§<kotlin.Any?>;1§<kotlin.Any?>} (0x3118a4)
        at kfun:kotlinx.coroutines.AbstractCoroutine#start(kotlinx.coroutines.CoroutineStart;0:0;kotlin.coroutines.SuspendFunction1<0:0,1:0>){0§<kotlin.Any?>} (0x2f8f69)
        at kfun:kotlinx.coroutines#launch$default@kotlinx.coroutines.CoroutineScope(kotlin.coroutines.CoroutineContext?;kotlinx.coroutines.CoroutineStart?;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,kotlin.Unit>;kotlin.Int){}kotlinx.coroutines.Job (0x2f9d37)
        at _636f6d2e636861706d616e3a626f6c742d646174612d636f6e73756d6572_kncfun86 (0x333419)
        at MQTTClient_run (0x34a3c3)
        at  (0x7f7e4de366db)
        at clone (0x7f7e4d947a3f)
        at  ((nil))
    I want to run IO bound tasks (network orientated) that run on a separate thread. The main thread with the linuxX64 target is mainly used for tasks that need to block (eg printing messages to the console). Linux unlike JS (the JavaScript platform) for example allows for multiple threads to run at once.
    d
    • 2
    • 4
  • s

    Sourabh Rawat

    07/02/2021, 2:52 AM
    I have this code
    class Executor {
        //    private val scope = CoroutineScope(Job() + Executors.newFixedThreadPool(10).asCoroutineDispatcher())
        private val context = Executors.newFixedThreadPool(10).asCoroutineDispatcher()
    
        suspend fun submit(value: Any) {
            withContext(context) {
                logger.debug { "Successfully received: $value" }
            }
        }
    
        fun stop() {
            // TODO
        }
    }
    How can I cancel the submitted jobs? And fail submission of a new job if the context is "cancelled"
    d
    u
    • 3
    • 3
  • w

    William Reed

    07/02/2021, 12:05 PM
    short of writing my own extension function, is there any more concise way of writing
    flow {
        emit(suspendFunction())
    }
    I know I could use
    flowOf(…)
    but the call site is not in a suspend function already
    a
    m
    u
    • 4
    • 5
  • f

    FoRRestDp

    07/03/2021, 4:56 PM
    Hi, is there good `suspend`ing equivalent for 
    ReadWriteLock
     in a library anywhere?
    m
    u
    • 3
    • 8
  • e

    Erik

    07/05/2021, 8:12 AM
    Is it possible to obtain a
    CoroutineContext
    from
    Thread.currentThread()
    ? I don't control the current thread instance, but I want to specifically switch to it using e.g.
    withContext(/*..*/) {}
    .
    m
    • 2
    • 11
  • n

    Noushad Chullian

    07/06/2021, 6:41 AM
    override suspend fun getProducts()=flow<State<List<ProductListFromEntity>>> {
                try {
                    val it = productDao.getProducts()
                    if (it.isEmpty()) {
                        loadProducts()
                    } else {
                       emit(State.success(it))
                    }
                }catch(e:Exception){
                    emit(State.error(e.localizedMessage.toString()))
                    e.printStackTrace()
                }
    }
    
    
    
    //Dao function
     @Query("SELECT product.productId, product.productCode, product.name FROM Product product")
        abstract suspend fun getProducts(): List<ProductListFromEntity>
        
    
    //viewModel
    suspend fun getProducts() {
            productRepository.getProducts().collectLatest {
                when (it) {
                    is State.Error -> {
                        _productListStates.value =
                            ProductListStates.Error(it.message, UIComponentType.Dialog())
                    }
                    is State.Success -> {
                        parseGivenProductList(it.data)
                    }
                }
            }
        }
    i am calling this function from viewmodel (android), But it is always throwing error saying,
    Child of the scoped flow was cancelled
    without any stacktrace. Am i doing anything wrong here...
    g
    n
    • 3
    • 77
  • e

    ermac10k

    07/06/2021, 1:04 PM
    Hello! if i have a coroutine task and i call a join on it
    task.join()
    and this join never returns than i do have a memory leak, don’t i?
    c
    n
    c
    • 4
    • 3
  • s

    Slackbot

    07/06/2021, 3:39 PM
    This message was deleted.
    d
    • 2
    • 1
  • x

    xxfast

    07/06/2021, 11:53 PM
    Hi all - is there a
    Flow<T>.flowOn(dispatcher)
    equivalent that that affects downstream? so that i can do
    results
      .map { result -> format(result) }
      .flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
      .collectOn(Dispatchers.Main)
      .collect { presenter.display(it) }
    instead of
    withContext(Dispatchers.Main) { 
      results
        .map { result -> format(result) }
        .flowOn(<http://Dispatchers.IO|Dispatchers.IO>)
        .collect {
          presenter.display(it)
        }
    }
    s
    u
    +3
    • 6
    • 9
  • g

    Gus

    07/07/2021, 10:45 AM
    Hi folks. I'm trying to upgrade from coroutines v1.3.9 to v1.5 in a Kotlin-based JVM library, but I'm struggling because of a change introduced in coroutines v1.4.0 (which doesn't seem mentioned on the release notes). I have a method where I'm using
    BroadcastChannel
    , but when I upgrade to coroutines 1.4.0 (or 1.5.0), the consumer's lambda function doesn't get called (even though my debugging shows that
    ackChannel.sendBlocking(...)
    is indeed called). Here's how it's consumed:
    ackChannel
                    .asFlow()
                    .onEach {
                        <http://logger.info|logger.info>("onEach called with $it")
                        ackObserver.onNext(it.toCargoDeliveryAck())
                    }
                    .onCompletion { ackObserver.onCompleted() }
                    .collect()
    (Full method definition on GitHub) I've also tried replacing the
    BroadcastChannel
    with
    MutableSharedFlow<String>(0, extraBufferCapacity = 1)
    (and replacing calls to
    ackChannel.sendBlocking()
    with
    mutableFlow.tryEmit()
    ), but the exact same issue persists. Any idea what I'm doing wrong? I created a PR where this issue is easily reproducible because it breaks a unit test.
    z
    • 2
    • 14
  • s

    Stefan Oltmann

    07/07/2021, 12:03 PM
    I want to create a Flow that is backed by something like a channel so I can emit values to it from the outside, but I don't figure out what's right here. Maybe "channelFlow()" is the correct thing, but I don't find a tutorial for that. 😕 I want to send URLs to a flow while a user scrolls through a photo gallery to process thumbnails. I don't want to span multiple coroutines that read from disk in parallel as this is a performance problem. Reading from disk should be in sequence, but after that creating thumbnails in memory can be done in parallel. What's a good way to achieve that?
    ✅ 1
    z
    • 2
    • 28
  • u

    ursus

    07/07/2021, 4:15 PM
    Hi,
    fun OkhttpAuthenticator.authenticate() {
    	...
    	synchronized(this) {
    		runBlocking { retrofitService.suspendingRefreshTokens() }<--- 
    		...
    	}
    }
    Could this get broken somehow? runBlocking seems to swap to caller thread context after the network call, so the mutex should be released or is it not guaranteed? (Because I see certain bugs in production where the code just stops; and not sure if its runBlocning or retrofit related)
    b
    • 2
    • 17
  • j

    jeggy

    07/07/2021, 11:02 PM
    I'm playing with flow and trying to integrate it with RabbitMQ. But I'm running into an issue where I can't emit values to a flow. I've created a simple example of my problem as shown on the image below. How would I solve this issue? If I try to run it in some other coroutine, Flow will just throw an error with the message
    Emission from another coroutine is detected.
    l
    • 2
    • 2
  • z

    zsperske

    07/07/2021, 11:37 PM
    Does anyone have any articles to share or recommendations on how to best live with both RXJava & coroutines in the same Android project? We’re going to be migrating over time and (understandably) a lot of the documentation assumes you are using all coroutines
    c
    j
    • 3
    • 8
  • f

    frankelot

    07/08/2021, 2:01 PM
    Why does
    .map
    on a
    StateFlow
    returns a
    Flow
    ?
    i
    a
    +2
    • 5
    • 71
  • m

    melatonina

    07/09/2021, 12:22 PM
    I want to be able to easily bind StateFlow, in particular as part of Android ViewModels. I'm going to use this code:
    interface BindableMutableStateFlow<T> : MutableStateFlow<T> {
        val coroutineScope: CoroutineScope
    
        fun bind(other: StateFlow<T>)
        fun unbind()
    }
    and
    fun <T> ViewModel.BindableMutableStateFlow(initialValue: T) : BindableMutableStateFlow<T> =
        MutableStateFlow<T>(initialValue).let { _stateFlow ->
            object : BindableMutableStateFlow<T>, MutableStateFlow<T> by _stateFlow {
                override val coroutineScope: CoroutineScope get() = viewModelScope
    
                private var job: Job? = null
                override fun bind(other: StateFlow<T>) {
                    unbind()
                    job = viewModelScope.launch {
                        other.collect {
                            value = it
                        }
                    }
                }
    
                override fun unbind() {
                    job?.cancel()
                    job = null
                }
            }
        }
    Am I duplicating or misusing (under-using) any existing Kotlin API? Do you see any problems with this code?
    w
    • 2
    • 18
  • w

    William Reed

    07/09/2021, 12:30 PM
    I have a
    MutableStateFlow<Map<..., ...>>
    what’s the most idiomatic way to mutate the map and update the
    StateFlow
    ? seems like I need to make a copy of the current value and then update it? something like this seems verbose and awkward
    stateFlow.value = stateFlow.value.toMutableMap().apply { … modify …}
    m
    n
    • 3
    • 3
  • v

    Vsevolod Tolstopyatov [JB]

    07/09/2021, 3:11 PM
    📣 📣 📣
    kotlinx.coroutines
    1.5.1 is here! • Bi-directional cancellation in Play Services integration • Behavioural improvements in
    CopyableThrowable
    • Fixed annoying but rare crash with
    java.lang.ClassCastException: kotlin.coroutines.jvm.internal.CompletedContinuation cannot be cast to kotlinx.coroutines.internal.DispatchedContinuation
    • New API reference site: https://kotlin.github.io/kotlinx.coroutines/ • Various bug fixes and improvements Full changelog: https://github.com/Kotlin/kotlinx.coroutines/releases/tag/1.5.1
    🎉 22
    j
    t
    • 3
    • 9
  • l

    Lilly

    07/09/2021, 5:04 PM
    Is there a convenient way to make a
    channelFlow
    hot? I would like to open a stream but defer the collecting. What I'm currently doing:
    // cold
    fun readByteArrayStream(): Flow<ByteArray> = channelFlow { .. }
    
    // hot
    val bytesChannel: Channel<ByteArray> by lazy { Channel(Channel.UNLIMITED) }
    
    suspend fun openByteArrayStream() {
            readByteArrayStream().onEach { bytesChannel.trySend(it) }.collect()
        }
    a
    • 2
    • 2
  • d

    Dominaezzz

    07/10/2021, 1:48 PM
    Why doesn't this deadlock?
    val stream = MutableSharedFlow<Unit>()
    val unused = stream.buffer(Channel.RENDEZVOUS).produceIn(GlobalScope)
    stream.emit(Unit)
    m
    z
    • 3
    • 28
  • e

    Eugen Martynov

    07/12/2021, 9:28 AM
    Maybe already asked - I run test with `
    runBlockingTest
    And it swallows exception without failing test
    • 1
    • 6
  • w

    William Reed

    07/12/2021, 2:18 PM
    when calling a
    suspend fun
    exposed from a library like
    Retrofit
    or
    Room
    or
    SqlDelight
    - is there a need to change the dispatcher to
    IO
    or since they are code generating a
    suspend fun
    is it safe to assume that its ‘main-safe’?
    j
    l
    +3
    • 6
    • 16
  • d

    Daniele Segato

    07/13/2021, 2:40 PM
    How can i trigger a non-blocking refresh inside a flow?
    getDataFlow()
      .onStart {
         coroutineScope {
             launch { repository.refresh() }
         } // this wait refresh to be finished
      }
    the above code in onStart wait the refresh to finish according to
    coroutineScope
    documentation, I need the
    repository.refresh()
    to run in parallel and just be canceled with the flow
    • 1
    • 1
  • v

    Vikas Singh

    07/13/2021, 5:08 PM
    CoroutineScope(Dispatchers.IO).launch{ print("This is before delay") delay(1000) print("This is after delay") } why does it not print after delay text
    z
    g
    • 3
    • 4
  • j

    julian

    07/13/2021, 9:23 PM
    I've observed that when an async-built-coroutine is nested within a launch-built-coroutine, the async-coroutine's job isn't added to the launch-coroutine's job's children. Is this always true?
    s
    • 2
    • 11
  • m

    marcinmoskala

    07/14/2021, 6:47 AM
    I wrote an article about dispatchers - how do they work and when do we use each of them 🙂 https://kt.academy/article/cc-dispatchers
    l
    • 2
    • 3
  • o

    Olli Helenius

    07/14/2021, 7:19 AM
    sorry about a possibly stupid question but is this:
    val x = (async { foo() }).await()
    ever different from just
    val x = foo()
    ?
    e
    u
    w
    • 4
    • 10
  • a

    Andrew Ebling

    07/14/2021, 3:37 PM
    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?
    embeddedServer(Netty, 8080) {
                routing {
                    get("/my_endpoint") {
                        triggerDataReadFromHardware()
                        while(hwData == null) { Thread.sleep(100) }
                        call.respond("${hwData!!}\n")
                        hwData = null
                    }
                }
            }.start(wait = false)
    e
    s
    • 3
    • 11
Powered by Linen
Title
a

Andrew Ebling

07/14/2021, 3:37 PM
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?
embeddedServer(Netty, 8080) {
            routing {
                get("/my_endpoint") {
                    triggerDataReadFromHardware()
                    while(hwData == null) { Thread.sleep(100) }
                    call.respond("${hwData!!}\n")
                    hwData = null
                }
            }
        }.start(wait = false)
e

ephemient

07/14/2021, 3:44 PM
does the hardware have a callback-based interface?
if so, it can be wrapped into a suspending function with suspendCoroutine or suspendCancellableCoroutine
a

Andrew Ebling

07/14/2021, 3:50 PM
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

streetsofboston

07/14/2021, 4:19 PM
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

Andrew Ebling

07/14/2021, 4:27 PM
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

ephemient

07/14/2021, 4:59 PM
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

streetsofboston

07/14/2021, 7:21 PM
Since you'd need to trigger the data-read, you may not need to poll continuously. Instead, you could get a deferred by calling
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.
View count: 3