Whats the concept behind a CoroutineScope?











up vote
4
down vote

favorite












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 at 13:42










  • To cancel the job's children
    – EpicPandaForce
    Nov 22 at 21:03















up vote
4
down vote

favorite












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 at 13:42










  • To cancel the job's children
    – EpicPandaForce
    Nov 22 at 21:03













up vote
4
down vote

favorite









up vote
4
down vote

favorite











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 at 14:41









Marko Topolnik

144k18193320




144k18193320










asked Nov 21 at 13:15









morpheus05

3,51122035




3,51122035












  • 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 at 13:42










  • To cancel the job's children
    – EpicPandaForce
    Nov 22 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 at 13:42










  • To cancel the job's children
    – EpicPandaForce
    Nov 22 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 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 at 13:42












To cancel the job's children
– EpicPandaForce
Nov 22 at 21:03




To cancel the job's children
– EpicPandaForce
Nov 22 at 21:03












3 Answers
3






active

oldest

votes

















up vote
3
down vote













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 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 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 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 at 19:46


















up vote
2
down vote













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




























    up vote
    0
    down vote













    This kotlinconf presentation presents an explanation of how coroutinesscope provide a useful failure domain, and also best practice conventions for defining your own methods.



    https://speakerdeck.com/elizarov/kotlin-coroutines-in-practice-at-kotlinconf-2018



    https://www.youtube.com/watch?v=a3agLJQ6vt8






    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',
      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

























      3 Answers
      3






      active

      oldest

      votes








      3 Answers
      3






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      3
      down vote













      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 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 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 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 at 19:46















      up vote
      3
      down vote













      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 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 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 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 at 19:46













      up vote
      3
      down vote










      up vote
      3
      down vote









      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 at 20:58

























      answered Nov 21 at 13:43









      s1m0nw1

      24k53797




      24k53797












      • 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 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 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 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 at 19:46


















      • 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 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 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 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 at 19:46
















      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 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 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 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 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 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 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 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 at 19:46












      up vote
      2
      down vote













      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

























        up vote
        2
        down vote













        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























          up vote
          2
          down vote










          up vote
          2
          down vote









          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 at 13:23









          Andrey Ilyunin

          744219




          744219






















              up vote
              0
              down vote













              This kotlinconf presentation presents an explanation of how coroutinesscope provide a useful failure domain, and also best practice conventions for defining your own methods.



              https://speakerdeck.com/elizarov/kotlin-coroutines-in-practice-at-kotlinconf-2018



              https://www.youtube.com/watch?v=a3agLJQ6vt8






              share|improve this answer

























                up vote
                0
                down vote













                This kotlinconf presentation presents an explanation of how coroutinesscope provide a useful failure domain, and also best practice conventions for defining your own methods.



                https://speakerdeck.com/elizarov/kotlin-coroutines-in-practice-at-kotlinconf-2018



                https://www.youtube.com/watch?v=a3agLJQ6vt8






                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  This kotlinconf presentation presents an explanation of how coroutinesscope provide a useful failure domain, and also best practice conventions for defining your own methods.



                  https://speakerdeck.com/elizarov/kotlin-coroutines-in-practice-at-kotlinconf-2018



                  https://www.youtube.com/watch?v=a3agLJQ6vt8






                  share|improve this answer












                  This kotlinconf presentation presents an explanation of how coroutinesscope provide a useful failure domain, and also best practice conventions for defining your own methods.



                  https://speakerdeck.com/elizarov/kotlin-coroutines-in-practice-at-kotlinconf-2018



                  https://www.youtube.com/watch?v=a3agLJQ6vt8







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 21 at 18:19









                  Yuri Schimke

                  3,14921221




                  3,14921221






























                       

                      draft saved


                      draft discarded



















































                       


                      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

                      Contact image not getting when fetch all contact list from iPhone by CNContact

                      count number of partitions of a set with n elements into k subsets

                      A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks