• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.coroutines
6 
7 import kotlinx.coroutines.internal.*
8 import java.util.concurrent.*
9 import java.util.concurrent.atomic.AtomicInteger
10 import kotlin.coroutines.*
11 
12 /**
13  * Creates a coroutine execution context using a single thread with built-in [yield] support.
14  * **NOTE: The resulting [ExecutorCoroutineDispatcher] owns native resources (its thread).
15  * Resources are reclaimed by [ExecutorCoroutineDispatcher.close].**
16  *
17  * If the resulting dispatcher is [closed][ExecutorCoroutineDispatcher.close] and
18  * attempt to submit a continuation task is made,
19  * then the [Job] of the affected task is [cancelled][Job.cancel] and the task is submitted to the
20  * [Dispatchers.IO], so that the affected coroutine can cleanup its resources and promptly complete.
21  *
22  * **NOTE: This API will be replaced in the future**. A different API to create thread-limited thread pools
23  * that is based on a shared thread-pool and does not require the resulting dispatcher to be explicitly closed
24  * will be provided, thus avoiding potential thread leaks and also significantly improving performance, due
25  * to coroutine-oriented scheduling policy and thread-switch minimization.
26  * See [issue #261](https://github.com/Kotlin/kotlinx.coroutines/issues/261) for details.
27  * If you need a completely separate thread-pool with scheduling policy that is based on the standard
28  * JDK executors, use the following expression:
29  * `Executors.newSingleThreadExecutor().asCoroutineDispatcher()`.
30  * See [Executor.asCoroutineDispatcher] for details.
31  *
32  * @param name the base name of the created thread.
33  */
34 @ObsoleteCoroutinesApi
35 public fun newSingleThreadContext(name: String): ExecutorCoroutineDispatcher =
36     newFixedThreadPoolContext(1, name)
37 
38 /**
39  * Creates a coroutine execution context with the fixed-size thread-pool and built-in [yield] support.
40  * **NOTE: The resulting [ExecutorCoroutineDispatcher] owns native resources (its threads).
41  * Resources are reclaimed by [ExecutorCoroutineDispatcher.close].**
42  *
43  * If the resulting dispatcher is [closed][ExecutorCoroutineDispatcher.close] and
44  * attempt to submit a continuation task is made,
45  * then the [Job] of the affected task is [cancelled][Job.cancel] and the task is submitted to the
46  * [Dispatchers.IO], so that the affected coroutine can cleanup its resources and promptly complete.
47  *
48  * **NOTE: This API will be replaced in the future**. A different API to create thread-limited thread pools
49  * that is based on a shared thread-pool and does not require the resulting dispatcher to be explicitly closed
50  * will be provided, thus avoiding potential thread leaks and also significantly improving performance, due
51  * to coroutine-oriented scheduling policy and thread-switch minimization.
52  * See [issue #261](https://github.com/Kotlin/kotlinx.coroutines/issues/261) for details.
53  * If you need a completely separate thread-pool with scheduling policy that is based on the standard
54  * JDK executors, use the following expression:
55  * `Executors.newFixedThreadPool().asCoroutineDispatcher()`.
56  * See [Executor.asCoroutineDispatcher] for details.
57  *
58  * @param nThreads the number of threads.
59  * @param name the base name of the created threads.
60  */
61 @ObsoleteCoroutinesApi
62 public fun newFixedThreadPoolContext(nThreads: Int, name: String): ExecutorCoroutineDispatcher {
63     require(nThreads >= 1) { "Expected at least one thread, but $nThreads specified" }
64     return ThreadPoolDispatcher(nThreads, name)
65 }
66 
67 internal class PoolThread(
68     @JvmField val dispatcher: ThreadPoolDispatcher, // for debugging & tests
69     target: Runnable, name: String
70 ) : Thread(target, name) {
71     init { isDaemon = true }
72 }
73 
74 /**
75  * Dispatches coroutine execution to a thread pool of a fixed size. Instances of this dispatcher are
76  * created with [newSingleThreadContext] and [newFixedThreadPoolContext].
77  */
78 internal class ThreadPoolDispatcher internal constructor(
79     private val nThreads: Int,
80     private val name: String
81 ) : ExecutorCoroutineDispatcherBase() {
82     private val threadNo = AtomicInteger()
83 
targetnull84     override val executor: Executor = Executors.newScheduledThreadPool(nThreads) { target ->
85         PoolThread(this, target, if (nThreads == 1) name else name + "-" + threadNo.incrementAndGet())
86     }
87 
88     init {
89         initFutureCancellation()
90     }
91 
92     /**
93      * Closes this dispatcher -- shuts down all threads in this pool and releases resources.
94      */
closenull95     public override fun close() {
96         (executor as ExecutorService).shutdown()
97     }
98 
toStringnull99     override fun toString(): String = "ThreadPoolDispatcher[$nThreads, $name]"
100 }
101