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

org.jetbrains.kotlinx.jupyter.streams.SubstitutionEngine.kt Maven / Gradle / Ivy

Go to download

Implementation of REPL compiler and preprocessor for Jupyter dialect of Kotlin (IDE-compatible)

The newest version!
package org.jetbrains.kotlinx.jupyter.streams

import org.jetbrains.kotlinx.jupyter.api.StreamSubstitutionType
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock

/**
 * Creates new data using possibly existing initial data
 */
typealias DataFactory = (initialData: DataT?) -> DataT

/**
 * Substitutes the shared data property with the `newData`. Returns previous value of the property
 */
typealias DataSubstitutor = (newData: DataT) -> DataT

/**
 * Substitutes old data back to the property. Possibly destroys newData as long it's no longer necessary
 */
typealias DataFinalizer = (newData: DataT, oldData: DataT) -> Unit

/**
 * Parameters of [SubstitutionEngine]
 */
class DataFlowComponents(
    val initialData: DataT,
    val substitutor: DataSubstitutor,
    val finalizer: DataFinalizer,
)

/**
 * Handles the logic of how data is created, when it's substituted instead of the previous value
 * of a shared resource, and how it's substituted back
 */
abstract class SubstitutionEngine(
    dataFlowComponents: DataFlowComponents,
) {
    protected val initialData: DataT = dataFlowComponents.initialData
    protected val substitutor: DataSubstitutor = dataFlowComponents.substitutor
    protected val finalizer: DataFinalizer = dataFlowComponents.finalizer

    /**
     * Substitutes the data provided by [dataFactory] instead of a shared resource
     * (which is done by [substitutor]), executes [body] in this context and calls
     * [finalizer] afterwards. Note that [finalizer] is called even in the case of exceptional
     * completion of [body].
     */
    abstract fun  withDataSubstitution(
        dataFactory: DataFactory,
        body: () -> T,
    ): T
}

/**
 * Implements the logic of substitution for [StreamSubstitutionType.BLOCKING]
 */
class BlockingSubstitutionEngine(
    dataFlowComponents: DataFlowComponents,
) : SubstitutionEngine(dataFlowComponents) {
    private val lock = ReentrantLock()

    override fun  withDataSubstitution(
        dataFactory: DataFactory,
        body: () -> T,
    ): T {
        val newData = dataFactory(initialData)
        return lock.withLock {
            val oldData = substitutor(newData)
            try {
                body()
            } finally {
                finalizer(newData, oldData)
            }
        }
    }
}

/**
 * Implements the logic of substitution for [StreamSubstitutionType.NON_BLOCKING]
 */
class NonBlockingSubstitutionEngine(
    dataFlowComponents: DataFlowComponents,
) : SubstitutionEngine(dataFlowComponents) {
    private val lock = ReentrantLock()
    private val dataList = DataList(initialData)

    override fun  withDataSubstitution(
        dataFactory: DataFactory,
        body: () -> T,
    ): T {
        val newData =
            lock.withLock {
                val myInitialData = dataList.last()
                val data = dataFactory(myInitialData)
                substitutor(data).also { _ ->
                    dataList.add(data)
                }
                data
            }

        return try {
            body()
        } finally {
            lock.withLock {
                with(dataList.remove(newData)) {
                    if (wasLast) {
                        finalizer(newData, newLast)
                    }
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy