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
  • s

    Shreyas Patil

    08/17/2020, 7:33 AM
    What's new in Coroutines 1.3.9? I can't find release notes
    z
    g
    +4
    • 7
    • 10
  • p

    phldavies

    08/17/2020, 9:11 AM
    Are there any examples/patterns for graceful shutdown with coroutines?
    g
    • 2
    • 4
  • u

    ubu

    08/17/2020, 11:29 AM
    Hi guys! There are scopes, like
    ViewModelScope
    from
    AAC
    , which works best for most of simple use cases, but when you want to cancel the job whose lifecycle is very specific, then there is a place for discussion. Suppose an operation should be run starting from
    onStart()
    call until there is a
    onStop()
    call. What would you suggest as good practice here to control this operation’s lifecycle? I started by creating custom scope, inside which this operation would run, then i realised, that after cancellation this scope can’t be re-used. Then I thought that creating a new scope every time
    onStart()
    is called is a bad idea (or not?). So I switched to a nullable variable holding a reference to a
    Job
    created after
    launch { ... }
    in
    onStart()
    , which I cancel in
    onStop()
    . Seems normal, but what if you want to cancel a lot of different jobs between `onStart()`/()`onStop()` calls? I might want a strange thing to do: having a scope, which, when you cancel it, cancel all its children job, but could be reset to allow new coroutines to run. Perhaps, I do not understand properly which logic stands behind not allowing to re-use cancelled scope. Thanks!
    e
    • 2
    • 2
  • m

    Maciek

    08/17/2020, 12:42 PM
    I'm creating a simple game loop in an Android app. I was just about to start writing this in a classic way with SurfaceView that holds and manages a Thread object. But we're in a world of coroutines now :coroutine: so why not use them also in this use-case. Do you see any potential downsides or problems with it? I'm doing something similar to this tutorial https://riptutorial.com/android/example/30741/game-using-canvas-and-surfaceview so some canvas locking, unlocking, looping and drawing
    e
    • 2
    • 2
  • c

    Carrascado

    08/17/2020, 5:02 PM
    I'm trying to understand the basics of Coroutines, the basics, but I don't understand at all what "suspending" means in this coroutines topic. Let's suppose I have my suspending function
    fun suspend foobar() { dostuff }
    , if I call that function from a coroutine, I understand from the documentation that calling foobar will suspend the coroutine, so does that mean foobar won't be executed? Why would I want to do that? It does not make any sense in my head. I know I must be understanding something really wrong
    z
    c
    +4
    • 7
    • 50
  • r

    rkeazor

    08/18/2020, 12:16 AM
    Updated to kotlin 1.4.0 with coroutines 1.3.9 but still dont see the coroutines debugger. Am I missing something
    o
    • 2
    • 8
  • s

    spierce7

    08/18/2020, 3:49 AM
    Looking to confirm. On a
    Channel
    I'd use
    consumeAsFlow
    if and only if the Flow was guaranteed to only have a single subscriber, but I'd use
    receiveAsFlow
    if one or multiple subscribers were possible, right?
    o
    • 2
    • 1
  • j

    jean

    08/18/2020, 10:54 AM
    In article like this one : https://quickbirdstudios.com/blog/android-mvi-kotlin-coroutines-flow/ I see the view model is handling intent by using
    viewModelScope
    to be able to use internal suspend function, and then use
    lifeCycleScope
    to observe the state flow variable. That leave us with two different coroutines, doesn’t it? Now I’m trying to test my code that use a similar approach and run in the situation where one of the mocked object used from the
    viewModelScope
    always return null regardless of the
    whenever
    mocking configuration. I stoped using the
    init
    block of my view model to jump start the handling of intent and replace it by a suspend fun, so now my view calls that function which returns the state flow to observe instead of the variable. This solved my null-value-mocked issue. Is that a better way way? Is there anything I’m not understanding?
    👍 1
    👀 2
    g
    • 2
    • 7
  • k

    kevinherron

    08/18/2020, 5:23 PM
    @elizarov do you have any thoughts or response to this comment by Ron? https://news.ycombinator.com/item?id=24197817
    ☝️ 1
    g
    e
    • 3
    • 18
  • l

    Luis Munoz

    08/18/2020, 10:15 PM
    I'm launching a million coroutines on Dispatchers.IO that do an HTTP post and then doing a joinAll but the loop gets stuck (posts stop being sent out). If I put a delay of 2 ms between each launch then it seems to work. Would it better to create my own thread pool? Or anyone have a guess of what the problem could be? Simplified Code:
    var scope = CoroutineScope(<http://Dispatchers.IO|Dispatchers.IO> + CoroutineName("myLoop"))
     job = scope.launch {
              while (this.isActive) {
                    (0 until appCfg.count).map {
                        delay(delayBetweenDeviceStarts)
                        val sn = appCfg.startSn + it
                        launch{
                          //  DO SOME HTTP OPERATIONS
                        }
                    }.joinAll()
              
                } 
    }
    t
    l
    • 3
    • 8
  • r

    rkeazor

    08/19/2020, 3:08 AM
    Anyone got the coroutines debugger to work on As 4.1
    r
    e
    • 3
    • 4
  • p

    pajatopmr

    08/19/2020, 9:44 AM
    IntelliJ reports the use of Reader.ready() as having the potential to block and thus "inappropriate" in a suspend function. But the JavaDoc says: "This method returns true if the next read() is guaranteed not to block for input, false otherwise. Note that returning false does not guarantee that the next read will block." So that leaves me thinking IntelliJ is wrong (a bug). Does JetBrains know something that is not in the documentation perhaps?
    e
    • 2
    • 4
  • g

    Gus

    08/19/2020, 9:52 AM
    Hey folks. I'm new to Kotlin and coroutines. I have a function that will return a
    Flow<Thingy>
    and, in some cases, that flow/job should be cancelled if no new
    Thingy
    has been emitted in the past X seconds (and I'll need to close an underlying connection when the flow is cancelled). Is there any readily-available utility to achieve this? If not, does anyone have any pointers on how to do this in an idiomatic way? If I have to implement it myself, I'm thinking of implementing it as two separate functions:
    getThingy(): Flow<Thingy>
    and
    getThingy(timeoutMillis: Int): Flow<Thingy>
    .
    getThingy()
    would return a cancellable flow, and
    getThingy(timeoutMillis)
    would use the former function behind the scenes and add the timeout logic. I'm thinking of using
    Timer.schedule()
    in the timeout logic so I can cancel the timer and start a new one each time a new
    Thingy
    is emitted, but I wonder whether there's a better way to do this.
    p
    • 2
    • 2
  • l

    Lukas Lechner

    08/19/2020, 12:33 PM
    Is it possible to install a
    CoroutineExceptionHandler
    in a
    viewModelScope
    when e.g. initialising an Android
    ViewModel
    ? I want that exceptions by every Coroutine that are then started in this scope are then handled by the handler.
    g
    c
    • 3
    • 3
  • t

    tylerwilson

    08/19/2020, 5:25 PM
    I updated my MP project which uses Ktor and coroutines to 1.4.0. I am getting this failure:
    Uncaught Kotlin exception: kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlinx.coroutines.ChildHandleNode@7eec8
    Anybody have any clues where to look? This same code worked in previous version…
    ➕ 1
    m
    • 2
    • 4
  • g

    Gus

    08/19/2020, 9:51 PM
    Hi there. Kotlin/coroutines newbie here. I have a function that opens a WebSocket connection to a server. The underlying protocol is very simple: The server sends a binary message (tagged with a unique id) and the client acknowledges it's safely stored the message by replying with a text message representing the message's unique id. I'm trying to model this with coroutines, but without leaking any details about the underlying implementation (e.g., the use of WebSockets). I basically want the user of my function to do something like this:
    retrieveMessages().map {
        File("the path").writeBytes(it.message)
        it.ack()
    }
    It's crucial that the ACK message be only sent to the server if and when the the incoming message is safely stored. That's why the ACK is explicit. I started to model this with a
    Flow<*>
    but I'm finding it rather cumbersome because I'd have to track all the unacknowledged messages so I won't close the connection too soon, which I think is a code smell since flows are supposed to be cold streams and therefore the underlying resource(s) should only be active while the flow is active. So for that reason I'm starting to question whether I should be using flows (or something like it) here, compared to just getting a callback to process each incoming message and sending the ACK to the server when the callback completes without errors; e.g.:
    retrieveMessages { message -> File("the path").writeBytes(message) }
    Thoughts?
    t
    • 2
    • 2
  • h

    hultgren

    08/20/2020, 1:21 AM
    When migrating my MP project (android+ios) to kotlin 1.4 I ran into a problem with publishing that seems to be related to coroutines
    1.3.9
    (the problem goes away if I use
    1.3.9-native-mt
    ). The project has the following dependencies:
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
    implementation "io.ktor:ktor-client-core:1.4.0"
    It's the task
    compileIosMainKotlinMetadata
    that fails with the following error:
    e: Could not find "kotlinx-coroutines-core_concurrentMain"
    Anyone else seen this?
    l
    h
    r
    • 4
    • 8
  • p

    phldavies

    08/20/2020, 9:02 AM
    What’s the best way to create a completable job as a child of the current scope?
    Job(parent = coroutineContext[Job])
    ?
    g
    • 2
    • 5
  • c

    Czar

    08/20/2020, 10:03 AM
    Hi, my use case is as follows: I have a table in postgres which contians events. I need to get batches of these events and process them in the application, processing is transactional. There is a draft implementation using scheduled thread pools, but it's quite convoluted, hard to follow and is plagued by race conditions and inconsistency. My task is to reimplement it. I wonder if there are any good methods of doing it with coroutines lib? Basically there is a 40 thread pool, each thread can process one event at a time. And there is a JPA repository that should be used in the producer (in reactive streams terminology) of those events. I need some kind of back-pressure setup, where the 40 thread pool is maximally utilized, but never overwhelmed. What are my options with coroutines? I looked at actors, but the relevant channel API seems to be obsoleted, and
    consumeEach
    assumes that the actor is temporary and will be closed after each message is processed, while in my case, the actor should probably persist, even if at the moment there are no new events. Another problem with actor is, that by making it unbounded I can run into OOM if there is a spike in events count, this is where I need backpressure and cannot just read events from the repository with constant rate.
    t
    d
    • 3
    • 5
  • g

    Gopal S Akshintala

    08/20/2020, 2:15 PM
    I saw this example in one of @elizarov’s articles https://medium.com/@elizarov/blocking-threads-suspending-coroutines-d33e11bf4761, about making CPU intensive call non-blocking. My doubt is as long as the work cannot be broken, this piece of code may not block main thread, but how can the Dispatcher make use of all cores on the system? Won't this just run on single background thread?
    suspend fun findBigPrime(): BigInteger =
        withContext(Dispatchers.Default) {
            BigInteger.probablePrime(4096, Random())
        }
    b
    z
    • 3
    • 6
  • n

    Nikky

    08/20/2020, 3:04 PM
    is there any library or core functionality for launching a job in a specific interval? or would a "simple"
    while(true) { launch { doJob() }: delay(..) }
    be the preferred solution ?
    g
    • 2
    • 3
  • p

    Pablo

    08/20/2020, 3:24 PM
    Hello I'm using the new version of Room and I'd like to start using
    Flow
    so what I want to do is change the
    List<Animals>
    to a
    Flow<List<Animals>>
    but then, I'm losing the mappers on my
    use-case
    and on my
    presentation
    ? Is there any way to keep mapping the values from the
    data
    layer? I mean, my dao now returns a
    Flow<List<Animals>>
    do I have to change also the repository return to be a
    Flow<List<Animals>>
    ? I had a return
    List<AnimalsMappedToDomain>
    , but now how can I do that mapper? What would be the flow from repository to presentation using the mappers?
    b
    • 2
    • 8
  • j

    jean

    08/20/2020, 4:33 PM
    I’m having an initialization issue with this code :
    lifecycleScope.launchWhenCreated {
                viewModel.state
                    .onEach { updateState(it) }
                    .onStart { inputsCollector.loadData() }
                    .launchIn(this)
    inputsCollector
    emit values on a channel when
    loadData
    is called, the values are then used by a state machine. the problem here is that
    inputsCollector.loadData()
    is called too soon, before the function in the state machine collects the values (I guess) even though I call that function before launching the coroutine. If I had
    delay(100)
    before
    inputsCollector.loadData()
    everything works fine. Any idea how when I should called
    inputsCollector.loadData()
    ?
    • 1
    • 1
  • v

    Vincent Williams

    08/20/2020, 4:52 PM
    private fun subscribeToViewModel() = lifecycleScope.launch(Dispatchers.Main) {
            viewModel.viewState.collect { onViewStateEvent(it) }
            viewModel.navigationEvents.collect { onNavigationEvent(it) }
        }
    This code doesnt seem to work. It only collects the first flow. Do I need to have two separate
    launch
    statements? Is there an easier way to do this as it gets a little messy with 3 or 4 flows
    l
    • 2
    • 11
  • s

    sean

    08/21/2020, 1:03 AM
    General question — When out refactoring some logic out of an existing suspend function which of these is preferred/best practice? If i'm starting with this and wanted to factor out the guts of `foo`:
    suspend fun doSomeWork(): Thing = supervisorScope {
      val foo = async {
        val result = async {
          fetchResultFromNetwork()
        }
    
        val otherResult = async {
          fetchOtherResultFromNetwork()
        }
        result.await() + otherResult.await()
      }
      
      val bar = async {
        anotherThing()
      }
      
      Thing(foo.await(), bar.await())
    }
    Would you go with: a) suspend fun + scope builder
    suspend fun doSomeWork(): Thing = supervisorScope {
      val foo = async {
        fetchAndMergeResults()
      }
      
      val bar = async {
        anotherThing()
      }
      
      Thing(foo.await(), bar.await())
    }
    
    suspend fun fetchAndMergeResults = coroutineScope {
      val result = async {
        fetchResultFromNetwork()
      }
    
      val otherResult = async {
        fetchOtherResultFromNetwork()
      }
      result.await() + otherResult.await()
    }
    b) Extension on CoroutineScope which returns a Deferred
    suspend fun doSomeWork(): Thing = supervisorScope {
      val foo = foo()
      
      val bar = async {
        anotherThing()
      }
      
      Thing(foo.await(), bar.await())
    }
    
    fun CoroutineScope.foo(): Deferred<Foo> {
      async {
        val result = async {
          fetchResultFromNetwork()
        }
    
        val otherResult = async {
          fetchOtherResultFromNetwork()
        }
        result.await() + otherResult.await()
      }
    }
    c) Something else? Any thoughts on what's preferred between the first two options? I'm aware of the conventions on suspend fun vs extension on CoroutineScope described in this video:

    https://youtu.be/hQrFfwT1IMo?t=2431▾

    and this blog post: https://medium.com/@elizarov/coroutine-context-and-scope-c8b255d59055 and I think both the examples above follow the convention, but I'm not sure if one is preferred in this case for one reason or another. Any opinions would be appreciated!
    g
    • 2
    • 7
  • v

    Vincent Williams

    08/21/2020, 4:19 PM
    private fun fetchData() = viewModelScope.launch(dispatcher) {
            repository.fetchData()
                    .onEach { 
                       //success
                    }
                    .catch { Timber.e(it) }
                    .launchIn(this)
        }
    Why is this still crashing my app when an exception occurs? should
    catch
    be catching that and not crashing?
    z
    s
    • 3
    • 34
  • f

    fkrauthan

    08/22/2020, 4:44 AM
    Hey I am working on a custom coroutine dispatcher for a programming game. I was wondering if anyone has experience doing that with Javascript to create a coroutine and then manual continue it onwards to create some sort of fake multi threading
    o
    • 2
    • 9
  • d

    Davide Giuseppe Farella

    08/22/2020, 2:12 PM
    Can somebody explain me why this fails with
    Test finished with active jobs
    scope.launch(Io) {
        withTimeout(500) {
            while (stack.isEmpty()) {
                delay(1) // await
            }
            result.data = stack.removeFirst()
        }
    }
    While this completes successfully
    val j = scope.launch(Io) {
        while (stack.isEmpty()) {
            delay(1) // await
        }
        result.data = stack.removeFirst()
    }
    scope.launch {
        delay(500)
        j.cancel()
    }
    t
    • 2
    • 4
  • g

    Gopal S Akshintala

    08/23/2020, 5:49 AM
    A Noob question, when I print
    Thread.currentThread().name
    , what exactly does
    @coroutine#id
    indicate (I understand it's an identifier to coroutine, but what exact piece of work does it indicate)? Is it the work the current thread does from one suspension point to till it encounters another suspension point? What exactly is a
    @coroutine#id
    physically translates to?
    o
    • 2
    • 5
  • g

    Gopal S Akshintala

    08/23/2020, 6:14 AM
    Noob question again, I wish to understand what happens underneath with coroutines. If the thread doesn't block, who does the actual work and calls the resume on the suspension point, for example
    delay()
    👍 1
    o
    • 2
    • 27
Powered by Linen
Title
g

Gopal S Akshintala

08/23/2020, 6:14 AM
Noob question again, I wish to understand what happens underneath with coroutines. If the thread doesn't block, who does the actual work and calls the resume on the suspension point, for example
delay()
👍 1
o

octylFractal

08/23/2020, 6:16 AM
delay
is actually one of the more complex bits, the specifics depend on the dispatcher you're using
if you're on JavaFx's Main dispatcher, it will re-use
Timer
to schedule and execute delays if you're on the Default dispatcher, it has its own scheduling logic that is very complex and can be viewed in
kotlinx.coroutines.EventLoop
and other classes
g

Gopal S Akshintala

08/23/2020, 6:23 AM
Ok, so it's more like event-driven, schedule an event after some T secs and when it's fired, resume the suspension, correct?
o

octylFractal

08/23/2020, 6:25 AM
I guess, for a loose definition of an "event". It just stores the Continuation and resumes it when the time is up, there's no event that's explicitly fired really (i.e. you won't find a ResumeEvent or DelayEvent)
I think internally the scheduling code uses the word "task", specifically "delayed task", which is more appropriate
g

Gopal S Akshintala

08/23/2020, 6:28 AM
Ok, but something has to keep track of the time and invoke something, so that continuation stored on heap is referred to resume from the point where it left before... I think that more of low-level... Taking a different example say a network call, does some low level stuff notify that hey I got all the data so you please resume?
o

octylFractal

08/23/2020, 6:30 AM
depends on how it's implemented 🙂 if it's just a wrapper over InputStream, it'll actually just switch over to Dispatchers.IO and block if it's using async IO, then usually that involves a selector thread that resumes coroutines that have data. you'd have to look at how ktor implements its sockets
g

Gopal S Akshintala

08/23/2020, 6:33 AM
Interesting, so with
<http://Dispatchers.IO|Dispatchers.IO>
how does "Thread doesn't block work? When I launch coroutines on
<http://Dispatchers.IO|Dispatchers.IO>
it spawns a large pool of threads, which eventually block and wait for the data, right?
o

octylFractal

08/23/2020, 6:34 AM
it's expected that code on
<http://Dispatchers.IO|Dispatchers.IO>
does block, it's the exception to allow compatibility with blocking code
g

Gopal S Akshintala

08/23/2020, 6:36 AM
Ooh... so if I have only one network call to make,
<http://Dispatchers.IO|Dispatchers.IO>
would allocate me one thread, which blocks on
InputStream
, right?
o

octylFractal

08/23/2020, 6:36 AM
yes
g

Gopal S Akshintala

08/23/2020, 6:37 AM
good to know... so it's as good as spawning a thread ourselves
so IO is handy when I have multiple concurrent network calls
o

octylFractal

08/23/2020, 6:38 AM
yes, though note it can still run out of threads (it only has max(64, # processors) by default)
g

Gopal S Akshintala

08/23/2020, 6:42 AM
that is right... where can I really leverage the "Light weight threads" philosophy, only for non-blocking operations?
like some concurrent computations?
o

octylFractal

08/23/2020, 6:44 AM
concurrent computations, more straightforward code when writing UI applications (you can easily swap between the UI thread and processing threads without needing any sort of concurrency system)
you can handle thousands of web requests without a large thread pool, by off-loading the IO to the IO dispatcher and having any waiting that needs to be done
suspend
rather than block
g

Gopal S Akshintala

08/23/2020, 6:47 AM
But with IO dispatcher, we are using a limited thread pool of 64 bg threads, how is different from having a server with 64 threads that are all blocked?
Plus I assume IO threads and Request-Executor threads, all come from same shared pool of threads, what are we saving here?
o

octylFractal

08/23/2020, 6:48 AM
that's true, you may need to look into using something like Ktor or custom code to use async IO
and the IO threads and Request-Executor threads are not the same, while
Dispatchers.Default
and
<http://Dispatchers.IO|Dispatchers.IO>
may share threads, if needed they will use new ones to their pool limit
g

Gopal S Akshintala

08/23/2020, 6:50 AM
Ok, so for a particular server, there is a separate pool that handles requests and separate for (IO + Default+ (... more on the run))?
o

octylFractal

08/23/2020, 6:51 AM
personally I would just handle requests on
Default
, that's part of the "lightweight" bit -- you don't really need a bunch of thread pools, you can mostly use the 2 given to you
you might use a custom IO dispatcher to increase the thread count, or you can just set the IO dispatcher's thread count via system property
unfortunately I can't really find a benchmark or anything about coroutine-based servers vs. normal Java servers
g

Gopal S Akshintala

08/23/2020, 7:33 AM
hmm ya, I tried searching for some benchmarks as well but in vain... Thanks alot @octylFractal for all the knowledge sharing 🙂
View count: 4