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