All Downloads are FREE. Search and download functionalities are using the official Maven repository.

.kotlinx.kotlinx-coroutines-debug.1.8.1.source-code.CoroutineInfo.kt Maven / Gradle / Ivy

There is a newer version: 1.10.1
Show newest version
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "UNUSED")
package kotlinx.coroutines.debug

import kotlinx.coroutines.*
import kotlinx.coroutines.debug.internal.*
import kotlin.coroutines.*
import kotlin.coroutines.jvm.internal.*

/**
 * Class describing coroutine info such as its context, state and stacktrace.
 */
@ExperimentalCoroutinesApi
public class CoroutineInfo internal constructor(delegate: DebugCoroutineInfo) {
    /**
     * [Coroutine context][coroutineContext] of the coroutine
     */
    public val context: CoroutineContext = delegate.context

    /**
     * Last observed state of the coroutine
     */
    public val state: State = State.valueOf(delegate.state)

    private val creationStackBottom: CoroutineStackFrame? = delegate.creationStackBottom

    /**
     * [Job] associated with a current coroutine or null.
     * May be later used in [DebugProbes.printJob].
     */
    public val job: Job? get() = context[Job]

    /**
     * Creation stacktrace of the coroutine.
     * Can be empty if [DebugProbes.enableCreationStackTraces] is not set.
     */
    public val creationStackTrace: List get() = creationStackTrace()

    private val lastObservedFrame: CoroutineStackFrame? = delegate.lastObservedFrame

    /**
     * Last observed stacktrace of the coroutine captured on its suspension or resumption point.
     * It means that for [running][State.RUNNING] coroutines resulting stacktrace is inaccurate and
     * reflects stacktrace of the resumption point, not the actual current stacktrace.
     */
    public fun lastObservedStackTrace(): List {
        var frame: CoroutineStackFrame? = lastObservedFrame ?: return emptyList()
        val result = ArrayList()
        while (frame != null) {
            frame.getStackTraceElement()?.let { result.add(it) }
            frame = frame.callerFrame
        }
        return result
    }

    private fun creationStackTrace(): List {
        val bottom = creationStackBottom ?: return emptyList()
        // Skip "Coroutine creation stacktrace" frame
        return sequence { yieldFrames(bottom.callerFrame) }.toList()
    }

    private tailrec suspend fun SequenceScope.yieldFrames(frame: CoroutineStackFrame?) {
        if (frame == null) return
        frame.getStackTraceElement()?.let { yield(it) }
        val caller = frame.callerFrame
        if (caller != null) {
            yieldFrames(caller)
        }
    }

    override fun toString(): String = "CoroutineInfo(state=$state,context=$context)"
}

/**
 * Current state of the coroutine.
 */
public enum class State {
    /**
     * Created, but not yet started.
     */
    CREATED,
    /**
     * Started and running.
     */
    RUNNING,
    /**
     * Suspended.
     */
    SUSPENDED
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy