[K/N] Implement Lazy for new mm
This commit is contained in:
@@ -8,53 +8,93 @@ package runtime.workers.lazy1
|
||||
import kotlin.test.*
|
||||
import kotlin.native.concurrent.*
|
||||
|
||||
class Lazy {
|
||||
private var y = 20
|
||||
|
||||
class Lazy(mode: LazyThreadSafetyMode) {
|
||||
val x = 17
|
||||
val self by lazy { this }
|
||||
val recursion: Int by lazy {
|
||||
val self by lazy(mode) { this }
|
||||
val recursion: Int by lazy(mode) {
|
||||
if (x < 17) 42 else recursion
|
||||
}
|
||||
val freezer: Int by lazy {
|
||||
val finiteRecursion : Int by lazy(mode) {
|
||||
if (y < 17) 42 else {
|
||||
y -= 1
|
||||
finiteRecursion + 1
|
||||
}
|
||||
}
|
||||
val freezer: Int by lazy(mode) {
|
||||
freeze()
|
||||
42
|
||||
}
|
||||
val thrower: String by lazy {
|
||||
val thrower: String by lazy(mode) {
|
||||
if (x < 100) throw IllegalArgumentException()
|
||||
"FAIL"
|
||||
}
|
||||
}
|
||||
|
||||
private val checkedLazyModes =
|
||||
if (Platform.memoryModel != MemoryModel.EXPERIMENTAL)
|
||||
listOf(LazyThreadSafetyMode.PUBLICATION)
|
||||
else
|
||||
listOf(LazyThreadSafetyMode.SYNCHRONIZED, LazyThreadSafetyMode.PUBLICATION)
|
||||
|
||||
@Test fun runTest1() {
|
||||
assertFailsWith<IllegalStateException> {
|
||||
println(Lazy().recursion)
|
||||
}
|
||||
assertFailsWith<IllegalStateException> {
|
||||
println(Lazy().freeze().recursion)
|
||||
for (mode in checkedLazyModes) {
|
||||
// We decided to synchonaize behaviour to be consistent with jvm version.
|
||||
// Anyway, it's doesn't looks like well-defined case
|
||||
if (Platform.memoryModel == MemoryModel.EXPERIMENTAL) {
|
||||
val expected = if (mode == LazyThreadSafetyMode.SYNCHRONIZED) 46 else 42
|
||||
y = 20
|
||||
assertEquals(Lazy(mode).finiteRecursion, expected)
|
||||
y = 20
|
||||
assertEquals(Lazy(mode).freeze().finiteRecursion, expected)
|
||||
} else {
|
||||
assertFailsWith<IllegalStateException> {
|
||||
println(Lazy(mode).recursion)
|
||||
}
|
||||
assertFailsWith<IllegalStateException> {
|
||||
println(Lazy(mode).freeze().recursion)
|
||||
}
|
||||
y = 20
|
||||
assertFailsWith<IllegalStateException> {
|
||||
println(Lazy(mode).finiteRecursion)
|
||||
}
|
||||
y = 20
|
||||
assertFailsWith<IllegalStateException> {
|
||||
println(Lazy(mode).freeze().finiteRecursion)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun runTest2() {
|
||||
var sum = 0
|
||||
for (i in 1 .. 100) {
|
||||
val self = Lazy().freeze()
|
||||
assertEquals(self, self.self)
|
||||
sum += self.self.hashCode()
|
||||
for (mode in checkedLazyModes) {
|
||||
var sum = 0
|
||||
for (i in 1..100) {
|
||||
val self = Lazy(mode).freeze()
|
||||
assertEquals(self, self.self)
|
||||
sum += self.self.hashCode()
|
||||
}
|
||||
}
|
||||
println("OK")
|
||||
}
|
||||
|
||||
|
||||
@Test fun runTest3() {
|
||||
assertFailsWith<InvalidMutabilityException> {
|
||||
println(Lazy().freezer)
|
||||
for (mode in checkedLazyModes) {
|
||||
assertFailsWith<InvalidMutabilityException> {
|
||||
println(Lazy(mode).freezer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun runTest4() {
|
||||
val self = Lazy()
|
||||
repeat(10) {
|
||||
assertFailsWith<IllegalArgumentException> {
|
||||
println(self.thrower)
|
||||
for (mode in checkedLazyModes) {
|
||||
val self = Lazy(mode)
|
||||
repeat(10) {
|
||||
assertFailsWith<IllegalArgumentException> {
|
||||
println(self.thrower)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,16 +11,20 @@ import kotlin.native.concurrent.*
|
||||
|
||||
const val WORKERS_COUNT = 20
|
||||
|
||||
class C(private val initializer: () -> Int) {
|
||||
val data by lazy { initializer() }
|
||||
class IntHolder(val value:Int)
|
||||
|
||||
class C(mode: LazyThreadSafetyMode, private val initializer: () -> IntHolder) {
|
||||
val data by lazy(mode) { initializer() }
|
||||
}
|
||||
|
||||
fun concurrentLazyAccess(freeze: Boolean) {
|
||||
fun concurrentLazyAccess(freeze: Boolean, mode: LazyThreadSafetyMode) {
|
||||
// in old mm PUBLICATION is in fact SYNCHRONIZED, while SYNCHRONIZED is not supported
|
||||
val argumentMode = if (Platform.memoryModel == MemoryModel.EXPERIMENTAL) mode else LazyThreadSafetyMode.PUBLICATION
|
||||
val initializerCallCount = AtomicInt(0)
|
||||
|
||||
val c = C {
|
||||
val c = C(argumentMode) {
|
||||
initializerCallCount.increment()
|
||||
42
|
||||
IntHolder(42)
|
||||
}
|
||||
if (freeze) {
|
||||
c.freeze()
|
||||
@@ -40,14 +44,18 @@ fun concurrentLazyAccess(freeze: Boolean) {
|
||||
while (inited.value < workers.size) {}
|
||||
canStart.value = 1
|
||||
|
||||
futures.forEach {
|
||||
assertEquals(42, it.result)
|
||||
val results = futures.map { it.result }
|
||||
results.forEach {
|
||||
assertEquals(42, it.value)
|
||||
assertSame(results[0], it)
|
||||
}
|
||||
workers.forEach {
|
||||
it.requestTermination().result
|
||||
}
|
||||
|
||||
assertEquals(1, initializerCallCount.value)
|
||||
if (mode == LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||
assertEquals(1, initializerCallCount.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -55,11 +63,13 @@ fun concurrentLazyAccessUnfrozen() {
|
||||
if (Platform.memoryModel != MemoryModel.EXPERIMENTAL) {
|
||||
return
|
||||
}
|
||||
concurrentLazyAccess(false)
|
||||
concurrentLazyAccess(false, LazyThreadSafetyMode.SYNCHRONIZED)
|
||||
concurrentLazyAccess(false, LazyThreadSafetyMode.PUBLICATION)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun concurrentLazyAccessFrozen() {
|
||||
concurrentLazyAccess(true)
|
||||
concurrentLazyAccess(true, LazyThreadSafetyMode.SYNCHRONIZED)
|
||||
concurrentLazyAccess(true, LazyThreadSafetyMode.PUBLICATION)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user