Skip to content

Commit f024608

Browse files
committed
Make AbstractCoroutine, JobSupport and LockFreeLinkedList public (but suppress from docs)
1 parent a198bad commit f024608

File tree

4 files changed

+98
-66
lines changed

4 files changed

+98
-66
lines changed

kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CoroutineScope.kt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,18 @@ public interface CoroutineScope {
4646

4747
/**
4848
* Abstract class to simplify writing of coroutine completion objects that
49-
* implements [Continuation] and [Job] interfaces.
49+
* implement completion [Continuation], [Job], and [CoroutineScope] interfaces.
5050
* It stores the result of continuation in the state of the job.
51+
*
52+
* @param context the new context for the coroutine. Use [newCoroutineContext] to create it.
53+
* @param active when `true` coroutine is created in _active_ state, when `false` in _new_ state. See [Job] for details.
54+
* @suppress **This is unstable API and it is subject to change.**
5155
*/
52-
@Suppress("LeakingThis")
53-
internal abstract class AbstractCoroutine<in T>(
56+
public abstract class AbstractCoroutine<in T>(
5457
context: CoroutineContext,
5558
active: Boolean
5659
) : JobSupport(active), Continuation<T>, CoroutineScope {
60+
@Suppress("LeakingThis")
5761
override val context: CoroutineContext = context + this // merges this job into this context
5862

5963
final override fun resume(value: T) {
@@ -85,4 +89,11 @@ internal abstract class AbstractCoroutine<in T>(
8589
final override fun handleCompletionException(closeException: Throwable) {
8690
handleCoroutineException(context, closeException)
8791
}
92+
93+
// for nicer debugging
94+
override fun toString(): String {
95+
val state = getState()
96+
val result = if (state is Incomplete) "" else "[$state]"
97+
return "${javaClass.simpleName}{${describeState(state)}}$result@${Integer.toHexString(System.identityHashCode(this))}"
98+
}
8899
}

kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Deferred.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,6 @@ private open class DeferredCoroutine<T>(
157157
if (state is CompletedExceptionally) throw state.exception
158158
return state as T
159159
}
160-
161-
// for nicer debugging
162-
override fun toString(): String {
163-
val state = getState()
164-
val result = if (state is Incomplete) "" else "[$state]"
165-
return "${javaClass.simpleName}{${describeState(state)}}$result@${Integer.toHexString(System.identityHashCode(this))}"
166-
}
167160
}
168161

169162
private class LazyDeferredCoroutine<T>(

kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Job.kt

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,11 @@ public fun Job.unregisterOnCompletion(registration: Job.Registration): Job.Regis
184184
public fun Job.cancelFutureOnCompletion(future: Future<*>): Job.Registration =
185185
onCompletion(CancelFutureOnCompletion(this, future))
186186

187-
internal fun Job.removeOnCompletion(node: LockFreeLinkedListNode): Job.Registration =
187+
/**
188+
* Removes a given node on completion.
189+
* @suppress **This is unstable API and it is subject to change.**
190+
*/
191+
public fun Job.removeOnCompletion(node: LockFreeLinkedListNode): Job.Registration =
188192
onCompletion(RemoveOnCompletion(this, node))
189193

190194
/**
@@ -214,9 +218,10 @@ public object EmptyRegistration : Job.Registration {
214218
* This is an open class designed for extension by more specific classes that might augment the
215219
* state and mare store addition state information for completed jobs, like their result values.
216220
*
217-
* Initial state of this job is either _active_ when `active = true` or _new_ when `active = false`.
221+
* @param active when `true` the job is created in _active_ state, when `false` in _new_ state. See [Job] for details.
222+
* @suppress **This is unstable API and it is subject to change.**
218223
*/
219-
internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElement(Job), Job {
224+
public open class JobSupport(active: Boolean) : AbstractCoroutineContextElement(Job), Job {
220225
/*
221226
=== Internal states ===
222227
@@ -279,7 +284,7 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
279284
* Initializes parent job.
280285
* It shall be invoked at most once after construction after all other initialization.
281286
*/
282-
fun initParentJob(parent: Job?) {
287+
public fun initParentJob(parent: Job?) {
283288
check(registration == null)
284289
if (parent == null) {
285290
registration = EmptyRegistration
@@ -295,26 +300,26 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
295300
/**
296301
* Returns current state of this job.
297302
*/
298-
fun getState(): Any? = state
303+
protected fun getState(): Any? = state
299304

300305
/**
301306
* Tries to update current [state][getState] of this job.
302307
*/
303-
fun updateState(expect: Any, update: Any?): Boolean {
308+
internal fun updateState(expect: Any, update: Any?): Boolean {
304309
if (!tryUpdateState(expect, update)) return false
305310
completeUpdateState(expect, update)
306311
return true
307312
}
308313

309-
fun tryUpdateState(expect: Any, update: Any?): Boolean {
314+
internal fun tryUpdateState(expect: Any, update: Any?): Boolean {
310315
require(expect is Incomplete && update !is Incomplete) // only incomplete -> completed transition is allowed
311316
if (!STATE.compareAndSet(this, expect, update)) return false
312317
// Unregister from parent job
313318
registration?.unregister() // volatile read registration _after_ state was updated
314319
return true // continues in completeUpdateState
315320
}
316321

317-
fun completeUpdateState(expect: Any, update: Any?) {
322+
internal fun completeUpdateState(expect: Any, update: Any?) {
318323
// Invoke completion handlers
319324
val cause = (update as? CompletedExceptionally)?.exception
320325
var completionException: Throwable? = null
@@ -335,7 +340,7 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
335340

336341
}
337342
// otherwise -- do nothing (it was Empty*)
338-
else -> check(expect === EmptyActive || expect == EmptyNew)
343+
else -> check(expect is Empty)
339344
}
340345
// Do other (overridable) processing after completion handlers
341346
completionException?.let { handleCompletionException(it) }
@@ -359,7 +364,7 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
359364
}
360365

361366
// return: 0 -> false (not new), 1 -> true (started), -1 -> retry
362-
protected fun startInternal(state: Any?): Int {
367+
internal fun startInternal(state: Any?): Int {
363368
when {
364369
// EMPTY_NEW state -- no completion handlers, new
365370
state === EmptyNew -> {
@@ -379,10 +384,12 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
379384
}
380385
}
381386

382-
// override to provide the actual start action
387+
/**
388+
* Override to provide the actual [start] action.
389+
*/
383390
protected open fun onStart() {}
384391

385-
override fun getCompletionException(): Throwable {
392+
final override fun getCompletionException(): Throwable {
386393
val state = getState()
387394
return when (state) {
388395
is Incomplete -> throw IllegalStateException("Job has not completed yet")
@@ -442,7 +449,7 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
442449
cont.unregisterOnCompletion(onCompletion(ResumeOnCompletion(this, cont)))
443450
}
444451

445-
fun removeNode(node: JobNode) {
452+
internal fun removeNode(node: JobNode) {
446453
// remove logic depends on the state of the job
447454
while (true) { // lock-free loop on job state
448455
val state = this.state
@@ -475,14 +482,14 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
475482
/**
476483
* Override to process any exceptions that were encountered while invoking [onCompletion] handlers.
477484
*/
478-
open fun handleCompletionException(closeException: Throwable) {
485+
protected open fun handleCompletionException(closeException: Throwable) {
479486
throw closeException
480487
}
481488

482489
/**
483490
* Override for post-completion actions that need to do something with the state.
484491
*/
485-
open fun afterCompletion(state: Any?) {}
492+
protected open fun afterCompletion(state: Any?) {}
486493

487494
private fun makeNode(handler: CompletionHandler): JobNode =
488495
(handler as? JobNode)?.also { require(it.job === this) }
@@ -494,20 +501,10 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
494501
/**
495502
* Interface for incomplete [state][getState] of a job.
496503
*/
497-
internal interface Incomplete {
504+
public interface Incomplete {
498505
val isActive: Boolean
499506
}
500507

501-
private object EmptyNew : Incomplete {
502-
override val isActive: Boolean get() = false
503-
override fun toString(): String = "Empty{New}"
504-
}
505-
506-
private object EmptyActive : Incomplete {
507-
override val isActive: Boolean get() = true
508-
override fun toString(): String = "Empty{Active}"
509-
}
510-
511508
private class NodeList(
512509
@Volatile
513510
var active: Int
@@ -535,12 +532,18 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
535532

536533
/**
537534
* Class for a [state][getState] of a job that had completed exceptionally, including cancellation.
535+
*
536+
* @param cause the exceptional completion cause. If `cause` is null, then a [CancellationException]
537+
* if created on first get from [exception] property.
538538
*/
539-
internal open class CompletedExceptionally(cause: Throwable?) {
539+
public open class CompletedExceptionally(cause: Throwable?) {
540540
@Volatile
541541
private var _exception: Throwable? = cause // materialize CancellationException on first need
542542

543-
val exception: Throwable get() =
543+
/**
544+
* Returns completion exception.
545+
*/
546+
public val exception: Throwable get() =
544547
_exception ?: // atomic read volatile var or else create new
545548
CancellationException("Job was cancelled").also { _exception = it }
546549

@@ -550,7 +553,14 @@ internal open class JobSupport(active: Boolean) : AbstractCoroutineContextElemen
550553
/**
551554
* A specific subclass of [CompletedExceptionally] for cancelled jobs.
552555
*/
553-
internal class Cancelled(cause: Throwable?) : CompletedExceptionally(cause)
556+
public class Cancelled(cause: Throwable?) : CompletedExceptionally(cause)
557+
}
558+
559+
private val EmptyNew = Empty(false)
560+
private val EmptyActive = Empty(true)
561+
562+
private class Empty(override val isActive: Boolean) : JobSupport.Incomplete {
563+
override fun toString(): String = "Empty{${if (isActive) "Active" else "New" }}"
554564
}
555565

556566
internal abstract class JobNode(

0 commit comments

Comments
 (0)