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

fuookami.ospf.kotlin.utils.context.Context.kt Maven / Gradle / Ivy

There is a newer version: 1.0.29
Show newest version
package fuookami.ospf.kotlin.utils.context

data class ContextKey(
    val thread: Thread,
    val stackTree: Array
) {
    companion object {
        private fun dump(stackTree: List): Array {
            if (stackTree.isEmpty()) {
                return emptyArray()
            }

            val topStack = stackTree[0]
            val normalizedTopStack = StackTraceElement(
                topStack.classLoaderName,
                topStack.moduleName,
                topStack.moduleVersion,
                topStack.className,
                topStack.methodName,
                topStack.fileName,
                -1
            )
            return (listOf(normalizedTopStack) + stackTree.toList().subList(1, stackTree.size)).toTypedArray()
        }

        operator fun invoke(): ContextKey {
            val stackTree = Thread.currentThread().stackTrace
            return ContextKey(
                thread = Thread.currentThread(),
                stackTree = dump(stackTree.toList().subList(3, stackTree.size - 1))
            )
        }
    }

    val parent by lazy {
        if (stackTree.isEmpty()) {
            null
        } else {
            ContextKey(
                thread = this.thread,
                stackTree = dump(stackTree.toList().subList(1, stackTree.size))
            )
        }
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is ContextKey) return false

        if (thread != other.thread) return false
        if (!(stackTree contentDeepEquals other.stackTree)) return false

        return true
    }

    override fun hashCode(): Int {
        var result = thread.hashCode()
        result = 31 * result + stackTree.contentDeepHashCode()
        return result
    }
}

class ContextVar(
    internal val defaultValue: T
) {
    @get:Synchronized
    internal val stackValues: MutableMap = hashMapOf(Pair(null, defaultValue))

    @Synchronized
    fun set(value: T): Context {
        stackValues[ContextKey()] = value
        return Context(this)
    }

    @Synchronized
    fun set(builder: () -> T): Context {
        stackValues[ContextKey()] = builder()
        return Context(this)
    }

    @Synchronized
    fun get(): T {
        var key: ContextKey? = ContextKey()
        while (!stackValues.containsKey(key)) {
            key = key?.parent
        }
        return stackValues[key]!!
    }
}

class Context(
    private val context: ContextVar
) {
    @Synchronized
    protected fun finalize() {
        var key: ContextKey? = ContextKey()
        while (!context.stackValues.containsKey(key)) {
            key = key?.parent
        }
        if (key != null) {
            context.stackValues.remove(key)
        }
    }
}

fun  context(contextVar: ContextVar, value: T? = null): Context {
    return if (value != null) {
        contextVar.set(value)
    } else {
        contextVar.set(contextVar.defaultValue)
    }
}

fun  context(contextVar: ContextVar, builder: (() -> T)? = null): Context {
    return if (builder != null) {
        contextVar.set(builder)
    } else {
        contextVar.set(contextVar.defaultValue)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy