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

jvmMain.io.ktor.util.AttributesJvm.kt Maven / Gradle / Ivy

/*
 * Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
 */

package io.ktor.util

import java.util.concurrent.*

/**
 * Create JVM specific attributes instance.
 */
public actual fun Attributes(concurrent: Boolean): Attributes =
    if (concurrent) ConcurrentSafeAttributes() else HashMapAttributes()

private abstract class AttributesJvmBase : Attributes {
    protected abstract val map: MutableMap, Any?>

    @Suppress("UNCHECKED_CAST")
    public final override fun  getOrNull(key: AttributeKey): T? = map[key] as T?

    public final override operator fun contains(key: AttributeKey<*>): Boolean = map.containsKey(key)

    public final override fun  put(key: AttributeKey, value: T) {
        map[key] = value
    }

    public final override fun  remove(key: AttributeKey) {
        map.remove(key)
    }

    public final override val allKeys: List>
        get() = map.keys.toList()
}

private class ConcurrentSafeAttributes : AttributesJvmBase() {
    override val map: ConcurrentHashMap, Any?> = ConcurrentHashMap()

    /**
     * Gets a value of the attribute for the specified [key], or calls supplied [block] to compute its value.
     * Note: [block] could be eventually evaluated twice for the same key.
     * TODO: To be discussed. Workaround for android < API 24.
     */
    override fun  computeIfAbsent(key: AttributeKey, block: () -> T): T {
        @Suppress("UNCHECKED_CAST")
        map[key]?.let { return it as T }
        val result = block()
        @Suppress("UNCHECKED_CAST")
        return (map.putIfAbsent(key, result) ?: result) as T
    }
}

private class HashMapAttributes : AttributesJvmBase() {
    override val map: MutableMap, Any?> = HashMap()

    /**
     * Gets a value of the attribute for the specified [key], or calls supplied [block] to compute its value.
     * Note: [block] could be eventually evaluated twice for the same key.
     * TODO: To be discussed. Workaround for android < API 24.
     */
    override fun  computeIfAbsent(key: AttributeKey, block: () -> T): T {
        @Suppress("UNCHECKED_CAST")
        map[key]?.let { return it as T }
        val result = block()
        @Suppress("UNCHECKED_CAST")
        return (map.put(key, result) ?: result) as T
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy