Skip to content
This repository has been archived by the owner on Feb 24, 2021. It is now read-only.

Make memoization compatible with MPP #331

Merged
merged 16 commits into from
Feb 18, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions arrow-syntax/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ plugins {
id "org.jlleitschuh.gradle.ktlint"
}

apply plugin: 'kotlinx-atomicfu'

apply from: "$SUB_PROJECT"
apply from: "$DOC_CREATION"
apply from: "$PUBLICATION"
Expand All @@ -13,4 +15,5 @@ dependencies {
testCompileOnly "org.jetbrains.kotlin:kotlin-reflect:$KOTLIN_VERSION"
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$JUNIT_VINTAGE_VERSION"
testImplementation project(":arrow-core-test")
testImplementation "io.arrow-kt:arrow-fx-coroutines:$VERSION_NAME"
}
117 changes: 113 additions & 4 deletions arrow-syntax/src/main/kotlin/arrow/syntax/function/memoization.kt
Original file line number Diff line number Diff line change
@@ -1,117 +1,208 @@
package arrow.syntax.function

import arrow.syntax.internal.Platform.newConcurrentMap

import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.loop

/**
* Memoizes the given **pure** function so that invocations with the same arguments will only execute the function once.
*
* ```kotlin:ank:playground
* import arrow.syntax.function.memoize
* fun someWorkIntensiveFunction(someParam: Int): String = "$someParam"
*
* fun main() {
* //sampleStart
* val memoizedF = ::someWorkIntensiveFunction.memoize()
*
* // The first invocation will store the argument and result in a cache inside the `memoizedF` reference.
* val value1 = memoizedF(42)
* // This second invocation won't really call the `someWorkIntensiveFunction` function
* //but retrieve the result from the previous invocation instead.
* val value2 = memoizedF(42)
*
* //sampleEnd
* println("$value1 $value2")
* }
* ```
*
* Note that calling this function with the same parameters in parallel might cause the function to be executed twice.
*/
fun <R> (() -> R).memoize(): () -> R = object : () -> R {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to define them as suspended functions. Given the nature of memoizing, or am I mistaken here?
cc @nomisRev

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR just updates the existing code to remove the dependency on Java classes. We can do a variant of this for suspending code as well.
Kinda silly that this needs to be defined separately tho, since normal code should work for suspending code. Only the other way around is not true.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the suspend version is the only pure/referential transparent implementation since it involves allocation mutable shared state to do the memoisation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that was one of my concerns.
Maybe it's worth deprecating it first and rolling out a suspended version either here or in Arrow Fx

private val m = MemoizedHandler<() -> R, MemoizeKey0<R>, R>(this@memoize)
override fun invoke(): R = m(MemoizeKey0(0))
}

/**
* @see memoize
*/
fun <P1, R> ((P1) -> R).memoize(): (P1) -> R = object : (P1) -> R {
private val m = MemoizedHandler<((P1) -> R), MemoizeKey1<P1, R>, R>(this@memoize)
override fun invoke(p1: P1) = m(MemoizeKey1(p1))
}

/**
* @see memoize
*/
fun <P1, P2, R> ((P1, P2) -> R).memoize(): (P1, P2) -> R = object : (P1, P2) -> R {
private val m = MemoizedHandler<((P1, P2) -> R), MemoizeKey2<P1, P2, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2) = m(MemoizeKey2(p1, p2))
}

/**
* @see memoize
*/
fun <P1, P2, P3, R> ((P1, P2, P3) -> R).memoize(): (P1, P2, P3) -> R = object : (P1, P2, P3) -> R {
private val m = MemoizedHandler<((P1, P2, P3) -> R), MemoizeKey3<P1, P2, P3, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3) = m(MemoizeKey3(p1, p2, p3))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, R> ((P1, P2, P3, P4) -> R).memoize(): (P1, P2, P3, P4) -> R = object : (P1, P2, P3, P4) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4) -> R), MemoizeKey4<P1, P2, P3, P4, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4) = m(MemoizeKey4(p1, p2, p3, p4))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, R> ((P1, P2, P3, P4, P5) -> R).memoize(): (P1, P2, P3, P4, P5) -> R = object : (P1, P2, P3, P4, P5) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5) -> R), MemoizeKey5<P1, P2, P3, P4, P5, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) = m(MemoizeKey5(p1, p2, p3, p4, p5))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, R> ((P1, P2, P3, P4, P5, P6) -> R).memoize(): (P1, P2, P3, P4, P5, P6) -> R = object : (P1, P2, P3, P4, P5, P6) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6) -> R), MemoizeKey6<P1, P2, P3, P4, P5, P6, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) = m(MemoizeKey6(p1, p2, p3, p4, p5, p6))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, R> ((P1, P2, P3, P4, P5, P6, P7) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7) -> R = object : (P1, P2, P3, P4, P5, P6, P7) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7) -> R), MemoizeKey7<P1, P2, P3, P4, P5, P6, P7, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) = m(MemoizeKey7(p1, p2, p3, p4, p5, p6, p7))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, R> ((P1, P2, P3, P4, P5, P6, P7, P8) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8) -> R), MemoizeKey8<P1, P2, P3, P4, P5, P6, P7, P8, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) = m(MemoizeKey8(p1, p2, p3, p4, p5, p6, p7, p8))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9) -> R), MemoizeKey9<P1, P2, P3, P4, P5, P6, P7, P8, P9, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) = m(MemoizeKey9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) -> R), MemoizeKey10<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10) = m(MemoizeKey10(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) -> R), MemoizeKey11<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11) = m(MemoizeKey11(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) -> R), MemoizeKey12<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12) = m(MemoizeKey12(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13) -> R), MemoizeKey13<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13) = m(MemoizeKey13(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) -> R), MemoizeKey14<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14) = m(MemoizeKey14(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) -> R), MemoizeKey15<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15) = m(MemoizeKey15(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) -> R), MemoizeKey16<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16) = m(MemoizeKey16(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17) -> R), MemoizeKey17<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17) = m(MemoizeKey17(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) -> R), MemoizeKey18<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18) = m(MemoizeKey18(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19) -> R), MemoizeKey19<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19) = m(MemoizeKey19(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) -> R), MemoizeKey20<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20) = m(MemoizeKey20(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21) -> R), MemoizeKey21<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21) = m(MemoizeKey21(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21))
}

/**
* @see memoize
*/
fun <P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, R> ((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R).memoize(): (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R = object : (P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R {
private val m = MemoizedHandler<((P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) -> R), MemoizeKey22<P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, R>, R>(this@memoize)
override fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22) = m(MemoizeKey22(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22))
Expand Down Expand Up @@ -214,6 +305,24 @@ private data class MemoizeKey22<out P1, out P2, out P3, out P4, out P5, out P6,
}

private class MemoizedHandler<F, in K : MemoizedCall<F, R>, out R>(val f: F) {
private val m = newConcurrentMap<K, R>()
operator fun invoke(k: K): R = m[k] ?: run { m.putSafely(k, k(f)) }
private val cache = atomic(emptyMap<K, R>())
operator fun invoke(k: K): R {
val cached = cache.value[k]
// No cached value found, compute one
return if (cached == null) {
val b = k(f)
cache.loop { old ->
val bb = old[k]
// No value is set yet (race condition)
if (bb == null) {
// Value was set, return the value
if (cache.compareAndSet(old, old + Pair(k, b))) return b
// keep looping failed to set
else Unit
// A value was already set first, return it
aballano marked this conversation as resolved.
Show resolved Hide resolved
} else return bb
}
// Cached value found, return it
} else cached
}
}
18 changes: 0 additions & 18 deletions arrow-syntax/src/main/kotlin/arrow/syntax/internal/Platform.kt

This file was deleted.