xref: /aosp_15_r20/external/kotlinx.coroutines/kotlinx-coroutines-core/common/src/NonCancellable.kt (revision 7a7160fed73afa6648ef8aa100d4a336fe921d9a)
1 @file:Suppress("DEPRECATION_ERROR")
2 
3 package kotlinx.coroutines
4 
5 import kotlinx.coroutines.selects.*
6 import kotlin.coroutines.*
7 
8 /**
9  * A non-cancelable job that is always [active][Job.isActive]. It is designed for [withContext] function
10  * to prevent cancellation of code blocks that need to be executed without cancellation.
11  *
12  * Use it like this:
13  * ```
14  * withContext(NonCancellable) {
15  *     // this code will not be cancelled
16  * }
17  * ```
18  *
19  * **WARNING**: This object is not designed to be used with [launch], [async], and other coroutine builders.
20  * if you write `launch(NonCancellable) { ... }` then not only the newly launched job will not be cancelled
21  * when the parent is cancelled, the whole parent-child relation between parent and child is severed.
22  * The parent will not wait for the child's completion, nor will be cancelled when the child crashed.
23  */
24 @Suppress("DeprecatedCallableAddReplaceWith")
25 public object NonCancellable : AbstractCoroutineContextElement(Job), Job {
26 
27     private const val message = "NonCancellable can be used only as an argument for 'withContext', direct usages of its API are prohibited"
28 
29     /**
30      * Always returns `null`.
31      * @suppress **This an internal API and should not be used from general code.**
32      */
33     @Deprecated(level = DeprecationLevel.WARNING, message = message)
34     override val parent: Job?
35         get() = null
36 
37     /**
38      * Always returns `true`.
39      * @suppress **This an internal API and should not be used from general code.**
40      */
41     @Deprecated(level = DeprecationLevel.WARNING, message = message)
42     override val isActive: Boolean
43         get() = true
44 
45     /**
46      * Always returns `false`.
47      * @suppress **This an internal API and should not be used from general code.**
48      */
49     @Deprecated(level = DeprecationLevel.WARNING, message = message)
50     override val isCompleted: Boolean get() = false
51 
52     /**
53      * Always returns `false`.
54      * @suppress **This an internal API and should not be used from general code.**
55      */
56     @Deprecated(level = DeprecationLevel.WARNING, message = message)
57     override val isCancelled: Boolean get() = false
58 
59     /**
60      * Always returns `false`.
61      * @suppress **This an internal API and should not be used from general code.**
62      */
63     @Deprecated(level = DeprecationLevel.WARNING, message = message)
startnull64     override fun start(): Boolean = false
65 
66     /**
67      * Always throws [UnsupportedOperationException].
68      * @suppress **This an internal API and should not be used from general code.**
69      */
70     @Deprecated(level = DeprecationLevel.WARNING, message = message)
71     override suspend fun join() {
72         throw UnsupportedOperationException("This job is always active")
73     }
74 
75     /**
76      * Always throws [UnsupportedOperationException].
77      * @suppress **This an internal API and should not be used from general code.**
78      */
79     @Deprecated(level = DeprecationLevel.WARNING, message = message)
80     override val onJoin: SelectClause0
81         get() = throw UnsupportedOperationException("This job is always active")
82 
83     /**
84      * Always throws [IllegalStateException].
85      * @suppress **This an internal API and should not be used from general code.**
86      */
87     @Deprecated(level = DeprecationLevel.WARNING, message = message)
getCancellationExceptionnull88     override fun getCancellationException(): CancellationException = throw IllegalStateException("This job is always active")
89 
90     /**
91      * @suppress **This an internal API and should not be used from general code.**
92      */
93     @Deprecated(level = DeprecationLevel.WARNING, message = message)
94     override fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle =
95         NonDisposableHandle
96 
97     /**
98      * Always returns no-op handle.
99      * @suppress **This an internal API and should not be used from general code.**
100      */
101     @Deprecated(level = DeprecationLevel.WARNING, message = message)
102     override fun invokeOnCompletion(onCancelling: Boolean, invokeImmediately: Boolean, handler: CompletionHandler): DisposableHandle =
103         NonDisposableHandle
104 
105     /**
106      * Does nothing.
107      * @suppress **This an internal API and should not be used from general code.**
108      */
109     @Deprecated(level = DeprecationLevel.WARNING, message = message)
110     override fun cancel(cause: CancellationException?) {}
111 
112     /**
113      * Always returns `false`.
114      * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [cancel].
115      */
116     @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
cancelnull117     override fun cancel(cause: Throwable?): Boolean = false // never handles exceptions
118 
119     /**
120      * Always returns [emptySequence].
121      * @suppress **This an internal API and should not be used from general code.**
122      */
123     @Deprecated(level = DeprecationLevel.WARNING, message = message)
124     override val children: Sequence<Job>
125         get() = emptySequence()
126 
127     /**
128      * Always returns [NonDisposableHandle] and does not do anything.
129      * @suppress **This an internal API and should not be used from general code.**
130      */
131     @Deprecated(level = DeprecationLevel.WARNING, message = message)
132     override fun attachChild(child: ChildJob): ChildHandle = NonDisposableHandle
133 
134     /** @suppress */
135     override fun toString(): String {
136         return "NonCancellable"
137     }
138 }
139