Whats the concept behind a CoroutineScope?












8















After reading the introduction and the javadoc of CoroutineScope I'm still a little confused what the idea behind a CoroutineScope is.



The first sentence of the doc "Defines a scope for new coroutines." is not clear to me: Why do my coroutines need a scope?



Also, why are standalone coroutine builders deprecated? Why is it better to do this:



fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
for (x in 1..5) send(x * x)
}


instead of



fun produceSquares(): ReceiveChannel<Int> = produce { //no longer an extension function
for (x in 1..5) send(x * x)
}









share|improve this question

























  • I found the description in this github issue useful to read: github.com/Kotlin/kotlinx.coroutines/issues/410. As explained there, "... coroutine builders like launch { ... } and async { ... } start a global coroutine by default... This seems to be a wrong default. Global coroutines are error-prone." Now you can still do the same as the old behaviour if you want, by using GlobalScope, but it means you're explicitly doing this instead of accidentally doing it. And it's recommended that in most cases you shouldn't use GlobalScope

    – Yoni Gibbs
    Nov 21 '18 at 13:42











  • To cancel the job's children

    – EpicPandaForce
    Nov 22 '18 at 21:03
















8















After reading the introduction and the javadoc of CoroutineScope I'm still a little confused what the idea behind a CoroutineScope is.



The first sentence of the doc "Defines a scope for new coroutines." is not clear to me: Why do my coroutines need a scope?



Also, why are standalone coroutine builders deprecated? Why is it better to do this:



fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
for (x in 1..5) send(x * x)
}


instead of



fun produceSquares(): ReceiveChannel<Int> = produce { //no longer an extension function
for (x in 1..5) send(x * x)
}









share|improve this question

























  • I found the description in this github issue useful to read: github.com/Kotlin/kotlinx.coroutines/issues/410. As explained there, "... coroutine builders like launch { ... } and async { ... } start a global coroutine by default... This seems to be a wrong default. Global coroutines are error-prone." Now you can still do the same as the old behaviour if you want, by using GlobalScope, but it means you're explicitly doing this instead of accidentally doing it. And it's recommended that in most cases you shouldn't use GlobalScope

    – Yoni Gibbs
    Nov 21 '18 at 13:42











  • To cancel the job's children

    – EpicPandaForce
    Nov 22 '18 at 21:03














8












8








8








After reading the introduction and the javadoc of CoroutineScope I'm still a little confused what the idea behind a CoroutineScope is.



The first sentence of the doc "Defines a scope for new coroutines." is not clear to me: Why do my coroutines need a scope?



Also, why are standalone coroutine builders deprecated? Why is it better to do this:



fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
for (x in 1..5) send(x * x)
}


instead of



fun produceSquares(): ReceiveChannel<Int> = produce { //no longer an extension function
for (x in 1..5) send(x * x)
}









share|improve this question
















After reading the introduction and the javadoc of CoroutineScope I'm still a little confused what the idea behind a CoroutineScope is.



The first sentence of the doc "Defines a scope for new coroutines." is not clear to me: Why do my coroutines need a scope?



Also, why are standalone coroutine builders deprecated? Why is it better to do this:



fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
for (x in 1..5) send(x * x)
}


instead of



fun produceSquares(): ReceiveChannel<Int> = produce { //no longer an extension function
for (x in 1..5) send(x * x)
}






kotlin kotlinx.coroutines






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 14:41









Marko Topolnik

148k19199328




148k19199328










asked Nov 21 '18 at 13:15









morpheus05morpheus05

3,63122136




3,63122136













  • I found the description in this github issue useful to read: github.com/Kotlin/kotlinx.coroutines/issues/410. As explained there, "... coroutine builders like launch { ... } and async { ... } start a global coroutine by default... This seems to be a wrong default. Global coroutines are error-prone." Now you can still do the same as the old behaviour if you want, by using GlobalScope, but it means you're explicitly doing this instead of accidentally doing it. And it's recommended that in most cases you shouldn't use GlobalScope

    – Yoni Gibbs
    Nov 21 '18 at 13:42











  • To cancel the job's children

    – EpicPandaForce
    Nov 22 '18 at 21:03



















  • I found the description in this github issue useful to read: github.com/Kotlin/kotlinx.coroutines/issues/410. As explained there, "... coroutine builders like launch { ... } and async { ... } start a global coroutine by default... This seems to be a wrong default. Global coroutines are error-prone." Now you can still do the same as the old behaviour if you want, by using GlobalScope, but it means you're explicitly doing this instead of accidentally doing it. And it's recommended that in most cases you shouldn't use GlobalScope

    – Yoni Gibbs
    Nov 21 '18 at 13:42











  • To cancel the job's children

    – EpicPandaForce
    Nov 22 '18 at 21:03

















I found the description in this github issue useful to read: github.com/Kotlin/kotlinx.coroutines/issues/410. As explained there, "... coroutine builders like launch { ... } and async { ... } start a global coroutine by default... This seems to be a wrong default. Global coroutines are error-prone." Now you can still do the same as the old behaviour if you want, by using GlobalScope, but it means you're explicitly doing this instead of accidentally doing it. And it's recommended that in most cases you shouldn't use GlobalScope

– Yoni Gibbs
Nov 21 '18 at 13:42





I found the description in this github issue useful to read: github.com/Kotlin/kotlinx.coroutines/issues/410. As explained there, "... coroutine builders like launch { ... } and async { ... } start a global coroutine by default... This seems to be a wrong default. Global coroutines are error-prone." Now you can still do the same as the old behaviour if you want, by using GlobalScope, but it means you're explicitly doing this instead of accidentally doing it. And it's recommended that in most cases you shouldn't use GlobalScope

– Yoni Gibbs
Nov 21 '18 at 13:42













To cancel the job's children

– EpicPandaForce
Nov 22 '18 at 21:03





To cancel the job's children

– EpicPandaForce
Nov 22 '18 at 21:03












2 Answers
2






active

oldest

votes


















5














You can still use global "standalone" coroutines by spawning them in GlobalScope:



GlobalScope.launch {
println("I'm running unstructured")
}


However, it's not recommended to do this since creating coroutines on a global scope is basically the same we did with good old threads. You create them but somehow need to keep track of a reference to later join/cancel them.



Using structured concurrency, that is nesting coroutines in their scopes, you will have a more maintainable system overall. For example, if you spawn a coroutine inside another one, you inherit the outer scope. This has multiple advantages. If you cancel the outer coroutine, the cancellation will be delegated to its inner coroutines. Also, you can be sure that the outer coroutine will not complete before all its children coroutines have done their work.



There's also a very good example shown in the documentation for CoroutineScope.




CoroutineScope should be implemented on entities with well-defined lifecycle that are responsible for launching children coroutines. Example of such entity on Android is Activity.




After all, the first version of your shown produceSquares methods is better as it is only executable if invoked in a CoroutineScope. That means you can run it inside any other coroutine:



launch {
produceSquares()
}


The coroutine created inside produceSquares inherits the scope of launch. You can be sure that launch does not complete before produceSquares. Also, if you cancelled launch, this would also effect produceSquares.



Furthermore, you can still create a globally running coroutine like this:



GlobalScope.produceSquares()


But, as mentioned, that's not the best option in most cases.



I'd also like to promote an article I wrote. There are some examples demonstrating what scopes mean: https://kotlinexpertise.com/kotlin-coroutines-concurrency/






share|improve this answer


























  • I'm still unsure what the actual Job of a Scope is in relation to a coroutine. Its lifetime and job handling? Association with the actual threads (I mean in the end, code has to be executed by a thread, so someone, somehow needs to decide on which thread a coroutine needs to be executed)

    – morpheus05
    Nov 21 '18 at 13:53











  • It’s about a coroutine‘s lifecycle in the end. The CoroutineDispatcher (just one part of the CoroutineScope) defines what threads to run on. You can for example say launch(Dispatchers.Default) to specify a dispatcher. Otherwise, you inherit from the outer scope

    – s1m0nw1
    Nov 21 '18 at 14:00













  • @morpheus05 Don't forget that the same coroutine can pass from thread to thread, there is no single decision on which thread it will run. While it's suspended, it's not assigned to any thread, and a new decision is made each time it resumes. You can also switch threads without suspending, using withContext. The best mental model to use is that a coroutine's "substrate" on which it runs is a thread, just like a CPU core is the substrate on which a thread runs.

    – Marko Topolnik
    Nov 21 '18 at 14:46













  • If I look at the CoroutineScope its an interface with one field, coroutineContext: CoroutineContext. But why then this interface? Can the context change during the lifecycle of a scope? Why was this interface introduced and lets say we would only work with CoroutineContext?

    – morpheus05
    Nov 21 '18 at 19:46











  • I have written an example (github.com/BILLyTheLiTTle/KotlinExperiments/blob/master/src/…) on my own just to understand. I am wondering, is there any advantage/disadvantage using GlobalScope.launch(Dispatchers.IO) {...} instead of CoroutineScope(Dispatchers.IO).launch {...} or vice versa?

    – LiTTle
    Jan 18 at 12:55



















2














It is related to the concept of structured concurrency, which defines a structure between coroutines.




On a more philosophical level, you rarely launch coroutines “globally”, like you do with threads. Coroutines are always related to some local scope in your application, which is an entity with a limited life-time, like a UI element. So, with structured concurrency we now require that launch is invoked in a CoroutineScope, which is an interface implemented by your life-time limited objects (like UI elements or their corresponding view models).




As an evident consequence of this concept: by cancelling the context of a scope, all it's subcoroutines will be canceled, too.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53412886%2fwhats-the-concept-behind-a-coroutinescope%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    5














    You can still use global "standalone" coroutines by spawning them in GlobalScope:



    GlobalScope.launch {
    println("I'm running unstructured")
    }


    However, it's not recommended to do this since creating coroutines on a global scope is basically the same we did with good old threads. You create them but somehow need to keep track of a reference to later join/cancel them.



    Using structured concurrency, that is nesting coroutines in their scopes, you will have a more maintainable system overall. For example, if you spawn a coroutine inside another one, you inherit the outer scope. This has multiple advantages. If you cancel the outer coroutine, the cancellation will be delegated to its inner coroutines. Also, you can be sure that the outer coroutine will not complete before all its children coroutines have done their work.



    There's also a very good example shown in the documentation for CoroutineScope.




    CoroutineScope should be implemented on entities with well-defined lifecycle that are responsible for launching children coroutines. Example of such entity on Android is Activity.




    After all, the first version of your shown produceSquares methods is better as it is only executable if invoked in a CoroutineScope. That means you can run it inside any other coroutine:



    launch {
    produceSquares()
    }


    The coroutine created inside produceSquares inherits the scope of launch. You can be sure that launch does not complete before produceSquares. Also, if you cancelled launch, this would also effect produceSquares.



    Furthermore, you can still create a globally running coroutine like this:



    GlobalScope.produceSquares()


    But, as mentioned, that's not the best option in most cases.



    I'd also like to promote an article I wrote. There are some examples demonstrating what scopes mean: https://kotlinexpertise.com/kotlin-coroutines-concurrency/






    share|improve this answer


























    • I'm still unsure what the actual Job of a Scope is in relation to a coroutine. Its lifetime and job handling? Association with the actual threads (I mean in the end, code has to be executed by a thread, so someone, somehow needs to decide on which thread a coroutine needs to be executed)

      – morpheus05
      Nov 21 '18 at 13:53











    • It’s about a coroutine‘s lifecycle in the end. The CoroutineDispatcher (just one part of the CoroutineScope) defines what threads to run on. You can for example say launch(Dispatchers.Default) to specify a dispatcher. Otherwise, you inherit from the outer scope

      – s1m0nw1
      Nov 21 '18 at 14:00













    • @morpheus05 Don't forget that the same coroutine can pass from thread to thread, there is no single decision on which thread it will run. While it's suspended, it's not assigned to any thread, and a new decision is made each time it resumes. You can also switch threads without suspending, using withContext. The best mental model to use is that a coroutine's "substrate" on which it runs is a thread, just like a CPU core is the substrate on which a thread runs.

      – Marko Topolnik
      Nov 21 '18 at 14:46













    • If I look at the CoroutineScope its an interface with one field, coroutineContext: CoroutineContext. But why then this interface? Can the context change during the lifecycle of a scope? Why was this interface introduced and lets say we would only work with CoroutineContext?

      – morpheus05
      Nov 21 '18 at 19:46











    • I have written an example (github.com/BILLyTheLiTTle/KotlinExperiments/blob/master/src/…) on my own just to understand. I am wondering, is there any advantage/disadvantage using GlobalScope.launch(Dispatchers.IO) {...} instead of CoroutineScope(Dispatchers.IO).launch {...} or vice versa?

      – LiTTle
      Jan 18 at 12:55
















    5














    You can still use global "standalone" coroutines by spawning them in GlobalScope:



    GlobalScope.launch {
    println("I'm running unstructured")
    }


    However, it's not recommended to do this since creating coroutines on a global scope is basically the same we did with good old threads. You create them but somehow need to keep track of a reference to later join/cancel them.



    Using structured concurrency, that is nesting coroutines in their scopes, you will have a more maintainable system overall. For example, if you spawn a coroutine inside another one, you inherit the outer scope. This has multiple advantages. If you cancel the outer coroutine, the cancellation will be delegated to its inner coroutines. Also, you can be sure that the outer coroutine will not complete before all its children coroutines have done their work.



    There's also a very good example shown in the documentation for CoroutineScope.




    CoroutineScope should be implemented on entities with well-defined lifecycle that are responsible for launching children coroutines. Example of such entity on Android is Activity.




    After all, the first version of your shown produceSquares methods is better as it is only executable if invoked in a CoroutineScope. That means you can run it inside any other coroutine:



    launch {
    produceSquares()
    }


    The coroutine created inside produceSquares inherits the scope of launch. You can be sure that launch does not complete before produceSquares. Also, if you cancelled launch, this would also effect produceSquares.



    Furthermore, you can still create a globally running coroutine like this:



    GlobalScope.produceSquares()


    But, as mentioned, that's not the best option in most cases.



    I'd also like to promote an article I wrote. There are some examples demonstrating what scopes mean: https://kotlinexpertise.com/kotlin-coroutines-concurrency/






    share|improve this answer


























    • I'm still unsure what the actual Job of a Scope is in relation to a coroutine. Its lifetime and job handling? Association with the actual threads (I mean in the end, code has to be executed by a thread, so someone, somehow needs to decide on which thread a coroutine needs to be executed)

      – morpheus05
      Nov 21 '18 at 13:53











    • It’s about a coroutine‘s lifecycle in the end. The CoroutineDispatcher (just one part of the CoroutineScope) defines what threads to run on. You can for example say launch(Dispatchers.Default) to specify a dispatcher. Otherwise, you inherit from the outer scope

      – s1m0nw1
      Nov 21 '18 at 14:00













    • @morpheus05 Don't forget that the same coroutine can pass from thread to thread, there is no single decision on which thread it will run. While it's suspended, it's not assigned to any thread, and a new decision is made each time it resumes. You can also switch threads without suspending, using withContext. The best mental model to use is that a coroutine's "substrate" on which it runs is a thread, just like a CPU core is the substrate on which a thread runs.

      – Marko Topolnik
      Nov 21 '18 at 14:46













    • If I look at the CoroutineScope its an interface with one field, coroutineContext: CoroutineContext. But why then this interface? Can the context change during the lifecycle of a scope? Why was this interface introduced and lets say we would only work with CoroutineContext?

      – morpheus05
      Nov 21 '18 at 19:46











    • I have written an example (github.com/BILLyTheLiTTle/KotlinExperiments/blob/master/src/…) on my own just to understand. I am wondering, is there any advantage/disadvantage using GlobalScope.launch(Dispatchers.IO) {...} instead of CoroutineScope(Dispatchers.IO).launch {...} or vice versa?

      – LiTTle
      Jan 18 at 12:55














    5












    5








    5







    You can still use global "standalone" coroutines by spawning them in GlobalScope:



    GlobalScope.launch {
    println("I'm running unstructured")
    }


    However, it's not recommended to do this since creating coroutines on a global scope is basically the same we did with good old threads. You create them but somehow need to keep track of a reference to later join/cancel them.



    Using structured concurrency, that is nesting coroutines in their scopes, you will have a more maintainable system overall. For example, if you spawn a coroutine inside another one, you inherit the outer scope. This has multiple advantages. If you cancel the outer coroutine, the cancellation will be delegated to its inner coroutines. Also, you can be sure that the outer coroutine will not complete before all its children coroutines have done their work.



    There's also a very good example shown in the documentation for CoroutineScope.




    CoroutineScope should be implemented on entities with well-defined lifecycle that are responsible for launching children coroutines. Example of such entity on Android is Activity.




    After all, the first version of your shown produceSquares methods is better as it is only executable if invoked in a CoroutineScope. That means you can run it inside any other coroutine:



    launch {
    produceSquares()
    }


    The coroutine created inside produceSquares inherits the scope of launch. You can be sure that launch does not complete before produceSquares. Also, if you cancelled launch, this would also effect produceSquares.



    Furthermore, you can still create a globally running coroutine like this:



    GlobalScope.produceSquares()


    But, as mentioned, that's not the best option in most cases.



    I'd also like to promote an article I wrote. There are some examples demonstrating what scopes mean: https://kotlinexpertise.com/kotlin-coroutines-concurrency/






    share|improve this answer















    You can still use global "standalone" coroutines by spawning them in GlobalScope:



    GlobalScope.launch {
    println("I'm running unstructured")
    }


    However, it's not recommended to do this since creating coroutines on a global scope is basically the same we did with good old threads. You create them but somehow need to keep track of a reference to later join/cancel them.



    Using structured concurrency, that is nesting coroutines in their scopes, you will have a more maintainable system overall. For example, if you spawn a coroutine inside another one, you inherit the outer scope. This has multiple advantages. If you cancel the outer coroutine, the cancellation will be delegated to its inner coroutines. Also, you can be sure that the outer coroutine will not complete before all its children coroutines have done their work.



    There's also a very good example shown in the documentation for CoroutineScope.




    CoroutineScope should be implemented on entities with well-defined lifecycle that are responsible for launching children coroutines. Example of such entity on Android is Activity.




    After all, the first version of your shown produceSquares methods is better as it is only executable if invoked in a CoroutineScope. That means you can run it inside any other coroutine:



    launch {
    produceSquares()
    }


    The coroutine created inside produceSquares inherits the scope of launch. You can be sure that launch does not complete before produceSquares. Also, if you cancelled launch, this would also effect produceSquares.



    Furthermore, you can still create a globally running coroutine like this:



    GlobalScope.produceSquares()


    But, as mentioned, that's not the best option in most cases.



    I'd also like to promote an article I wrote. There are some examples demonstrating what scopes mean: https://kotlinexpertise.com/kotlin-coroutines-concurrency/







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 22 '18 at 20:58

























    answered Nov 21 '18 at 13:43









    s1m0nw1s1m0nw1

    28.9k653110




    28.9k653110













    • I'm still unsure what the actual Job of a Scope is in relation to a coroutine. Its lifetime and job handling? Association with the actual threads (I mean in the end, code has to be executed by a thread, so someone, somehow needs to decide on which thread a coroutine needs to be executed)

      – morpheus05
      Nov 21 '18 at 13:53











    • It’s about a coroutine‘s lifecycle in the end. The CoroutineDispatcher (just one part of the CoroutineScope) defines what threads to run on. You can for example say launch(Dispatchers.Default) to specify a dispatcher. Otherwise, you inherit from the outer scope

      – s1m0nw1
      Nov 21 '18 at 14:00













    • @morpheus05 Don't forget that the same coroutine can pass from thread to thread, there is no single decision on which thread it will run. While it's suspended, it's not assigned to any thread, and a new decision is made each time it resumes. You can also switch threads without suspending, using withContext. The best mental model to use is that a coroutine's "substrate" on which it runs is a thread, just like a CPU core is the substrate on which a thread runs.

      – Marko Topolnik
      Nov 21 '18 at 14:46













    • If I look at the CoroutineScope its an interface with one field, coroutineContext: CoroutineContext. But why then this interface? Can the context change during the lifecycle of a scope? Why was this interface introduced and lets say we would only work with CoroutineContext?

      – morpheus05
      Nov 21 '18 at 19:46











    • I have written an example (github.com/BILLyTheLiTTle/KotlinExperiments/blob/master/src/…) on my own just to understand. I am wondering, is there any advantage/disadvantage using GlobalScope.launch(Dispatchers.IO) {...} instead of CoroutineScope(Dispatchers.IO).launch {...} or vice versa?

      – LiTTle
      Jan 18 at 12:55



















    • I'm still unsure what the actual Job of a Scope is in relation to a coroutine. Its lifetime and job handling? Association with the actual threads (I mean in the end, code has to be executed by a thread, so someone, somehow needs to decide on which thread a coroutine needs to be executed)

      – morpheus05
      Nov 21 '18 at 13:53











    • It’s about a coroutine‘s lifecycle in the end. The CoroutineDispatcher (just one part of the CoroutineScope) defines what threads to run on. You can for example say launch(Dispatchers.Default) to specify a dispatcher. Otherwise, you inherit from the outer scope

      – s1m0nw1
      Nov 21 '18 at 14:00













    • @morpheus05 Don't forget that the same coroutine can pass from thread to thread, there is no single decision on which thread it will run. While it's suspended, it's not assigned to any thread, and a new decision is made each time it resumes. You can also switch threads without suspending, using withContext. The best mental model to use is that a coroutine's "substrate" on which it runs is a thread, just like a CPU core is the substrate on which a thread runs.

      – Marko Topolnik
      Nov 21 '18 at 14:46













    • If I look at the CoroutineScope its an interface with one field, coroutineContext: CoroutineContext. But why then this interface? Can the context change during the lifecycle of a scope? Why was this interface introduced and lets say we would only work with CoroutineContext?

      – morpheus05
      Nov 21 '18 at 19:46











    • I have written an example (github.com/BILLyTheLiTTle/KotlinExperiments/blob/master/src/…) on my own just to understand. I am wondering, is there any advantage/disadvantage using GlobalScope.launch(Dispatchers.IO) {...} instead of CoroutineScope(Dispatchers.IO).launch {...} or vice versa?

      – LiTTle
      Jan 18 at 12:55

















    I'm still unsure what the actual Job of a Scope is in relation to a coroutine. Its lifetime and job handling? Association with the actual threads (I mean in the end, code has to be executed by a thread, so someone, somehow needs to decide on which thread a coroutine needs to be executed)

    – morpheus05
    Nov 21 '18 at 13:53





    I'm still unsure what the actual Job of a Scope is in relation to a coroutine. Its lifetime and job handling? Association with the actual threads (I mean in the end, code has to be executed by a thread, so someone, somehow needs to decide on which thread a coroutine needs to be executed)

    – morpheus05
    Nov 21 '18 at 13:53













    It’s about a coroutine‘s lifecycle in the end. The CoroutineDispatcher (just one part of the CoroutineScope) defines what threads to run on. You can for example say launch(Dispatchers.Default) to specify a dispatcher. Otherwise, you inherit from the outer scope

    – s1m0nw1
    Nov 21 '18 at 14:00







    It’s about a coroutine‘s lifecycle in the end. The CoroutineDispatcher (just one part of the CoroutineScope) defines what threads to run on. You can for example say launch(Dispatchers.Default) to specify a dispatcher. Otherwise, you inherit from the outer scope

    – s1m0nw1
    Nov 21 '18 at 14:00















    @morpheus05 Don't forget that the same coroutine can pass from thread to thread, there is no single decision on which thread it will run. While it's suspended, it's not assigned to any thread, and a new decision is made each time it resumes. You can also switch threads without suspending, using withContext. The best mental model to use is that a coroutine's "substrate" on which it runs is a thread, just like a CPU core is the substrate on which a thread runs.

    – Marko Topolnik
    Nov 21 '18 at 14:46







    @morpheus05 Don't forget that the same coroutine can pass from thread to thread, there is no single decision on which thread it will run. While it's suspended, it's not assigned to any thread, and a new decision is made each time it resumes. You can also switch threads without suspending, using withContext. The best mental model to use is that a coroutine's "substrate" on which it runs is a thread, just like a CPU core is the substrate on which a thread runs.

    – Marko Topolnik
    Nov 21 '18 at 14:46















    If I look at the CoroutineScope its an interface with one field, coroutineContext: CoroutineContext. But why then this interface? Can the context change during the lifecycle of a scope? Why was this interface introduced and lets say we would only work with CoroutineContext?

    – morpheus05
    Nov 21 '18 at 19:46





    If I look at the CoroutineScope its an interface with one field, coroutineContext: CoroutineContext. But why then this interface? Can the context change during the lifecycle of a scope? Why was this interface introduced and lets say we would only work with CoroutineContext?

    – morpheus05
    Nov 21 '18 at 19:46













    I have written an example (github.com/BILLyTheLiTTle/KotlinExperiments/blob/master/src/…) on my own just to understand. I am wondering, is there any advantage/disadvantage using GlobalScope.launch(Dispatchers.IO) {...} instead of CoroutineScope(Dispatchers.IO).launch {...} or vice versa?

    – LiTTle
    Jan 18 at 12:55





    I have written an example (github.com/BILLyTheLiTTle/KotlinExperiments/blob/master/src/…) on my own just to understand. I am wondering, is there any advantage/disadvantage using GlobalScope.launch(Dispatchers.IO) {...} instead of CoroutineScope(Dispatchers.IO).launch {...} or vice versa?

    – LiTTle
    Jan 18 at 12:55













    2














    It is related to the concept of structured concurrency, which defines a structure between coroutines.




    On a more philosophical level, you rarely launch coroutines “globally”, like you do with threads. Coroutines are always related to some local scope in your application, which is an entity with a limited life-time, like a UI element. So, with structured concurrency we now require that launch is invoked in a CoroutineScope, which is an interface implemented by your life-time limited objects (like UI elements or their corresponding view models).




    As an evident consequence of this concept: by cancelling the context of a scope, all it's subcoroutines will be canceled, too.






    share|improve this answer




























      2














      It is related to the concept of structured concurrency, which defines a structure between coroutines.




      On a more philosophical level, you rarely launch coroutines “globally”, like you do with threads. Coroutines are always related to some local scope in your application, which is an entity with a limited life-time, like a UI element. So, with structured concurrency we now require that launch is invoked in a CoroutineScope, which is an interface implemented by your life-time limited objects (like UI elements or their corresponding view models).




      As an evident consequence of this concept: by cancelling the context of a scope, all it's subcoroutines will be canceled, too.






      share|improve this answer


























        2












        2








        2







        It is related to the concept of structured concurrency, which defines a structure between coroutines.




        On a more philosophical level, you rarely launch coroutines “globally”, like you do with threads. Coroutines are always related to some local scope in your application, which is an entity with a limited life-time, like a UI element. So, with structured concurrency we now require that launch is invoked in a CoroutineScope, which is an interface implemented by your life-time limited objects (like UI elements or their corresponding view models).




        As an evident consequence of this concept: by cancelling the context of a scope, all it's subcoroutines will be canceled, too.






        share|improve this answer













        It is related to the concept of structured concurrency, which defines a structure between coroutines.




        On a more philosophical level, you rarely launch coroutines “globally”, like you do with threads. Coroutines are always related to some local scope in your application, which is an entity with a limited life-time, like a UI element. So, with structured concurrency we now require that launch is invoked in a CoroutineScope, which is an interface implemented by your life-time limited objects (like UI elements or their corresponding view models).




        As an evident consequence of this concept: by cancelling the context of a scope, all it's subcoroutines will be canceled, too.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 21 '18 at 13:23









        Andrey IlyuninAndrey Ilyunin

        1,402221




        1,402221






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53412886%2fwhats-the-concept-behind-a-coroutinescope%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How to send String Array data to Server using php in android

            Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

            Is anime1.com a legal site for watching anime?