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 `null`. 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 parent: Job? 38 get() = null 39 40 /** 41 * Always returns `true`. 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 isActive: Boolean 46 get() = true 47 48 /** 49 * Always returns `false`. 50 * @suppress **This an internal API and should not be used from general code.** 51 */ 52 @Deprecated(level = DeprecationLevel.WARNING, message = message) 53 override val isCompleted: Boolean get() = false 54 55 /** 56 * Always returns `false`. 57 * @suppress **This an internal API and should not be used from general code.** 58 */ 59 @Deprecated(level = DeprecationLevel.WARNING, message = message) 60 override val isCancelled: Boolean get() = false 61 62 /** 63 * Always returns `false`. 64 * @suppress **This an internal API and should not be used from general code.** 65 */ 66 @Deprecated(level = DeprecationLevel.WARNING, message = message) startnull67 override fun start(): Boolean = false 68 69 /** 70 * Always throws [UnsupportedOperationException]. 71 * @suppress **This an internal API and should not be used from general code.** 72 */ 73 @Deprecated(level = DeprecationLevel.WARNING, message = message) 74 override suspend fun join() { 75 throw UnsupportedOperationException("This job is always active") 76 } 77 78 /** 79 * Always throws [UnsupportedOperationException]. 80 * @suppress **This an internal API and should not be used from general code.** 81 */ 82 @Deprecated(level = DeprecationLevel.WARNING, message = message) 83 override val onJoin: SelectClause0 84 get() = throw UnsupportedOperationException("This job is always active") 85 86 /** 87 * Always throws [IllegalStateException]. 88 * @suppress **This an internal API and should not be used from general code.** 89 */ 90 @Deprecated(level = DeprecationLevel.WARNING, message = message) getCancellationExceptionnull91 override fun getCancellationException(): CancellationException = throw IllegalStateException("This job is always active") 92 93 /** 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(handler: CompletionHandler): DisposableHandle = 98 NonDisposableHandle 99 100 /** 101 * Always returns no-op handle. 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 invokeOnCompletion(onCancelling: Boolean, invokeImmediately: Boolean, handler: CompletionHandler): DisposableHandle = 106 NonDisposableHandle 107 108 /** 109 * Does nothing. 110 * @suppress **This an internal API and should not be used from general code.** 111 */ 112 @Deprecated(level = DeprecationLevel.WARNING, message = message) 113 override fun cancel(cause: CancellationException?) {} 114 115 /** 116 * Always returns `false`. 117 * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [cancel]. 118 */ 119 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x") cancelnull120 override fun cancel(cause: Throwable?): Boolean = false // never handles exceptions 121 122 /** 123 * Always returns [emptySequence]. 124 * @suppress **This an internal API and should not be used from general code.** 125 */ 126 @Deprecated(level = DeprecationLevel.WARNING, message = message) 127 override val children: Sequence<Job> 128 get() = emptySequence() 129 130 /** 131 * Always returns [NonDisposableHandle] and does not do anything. 132 * @suppress **This an internal API and should not be used from general code.** 133 */ 134 @Deprecated(level = DeprecationLevel.WARNING, message = message) 135 override fun attachChild(child: ChildJob): ChildHandle = NonDisposableHandle 136 137 /** @suppress */ 138 override fun toString(): String { 139 return "NonCancellable" 140 } 141 } 142