// TODO(KT-65977): reenable these tests with caches //IGNORE_NATIVE: cacheMode=STATIC_EVERYWHERE //IGNORE_NATIVE: cacheMode=STATIC_PER_FILE_EVERYWHERE import kotlinx.atomicfu.* import kotlin.test.* class LockFreeStackTest { fun testClear() { val s = LockFreeStack() assertTrue(s.isEmpty()) s.pushLoop("A") assertTrue(!s.isEmpty()) s.clear() assertTrue(s.isEmpty()) } fun testPushPopLoop() { val s = LockFreeStack() assertTrue(s.isEmpty()) s.pushLoop("A") assertTrue(!s.isEmpty()) assertEquals("A", s.popLoop()) assertTrue(s.isEmpty()) } fun testPushPopUpdate() { val s = LockFreeStack() assertTrue(s.isEmpty()) s.pushUpdate("A") assertTrue(!s.isEmpty()) assertEquals("A", s.popUpdate()) assertTrue(s.isEmpty()) } } class LockFreeStack { private val top = atomic?>(null) private class Node(val value: T, val next: Node?) fun isEmpty() = top.value == null fun clear() { top.value = null } fun pushLoop(value: T) { top.loop { cur -> val upd = Node(value, cur) if (top.compareAndSet(cur, upd)) return } } fun popLoop(): T? { top.loop { cur -> if (cur == null) return null if (top.compareAndSet(cur, cur.next)) return cur.value } } fun pushUpdate(value: T) { top.update { cur -> Node(value, cur) } } fun popUpdate(): T? = top.getAndUpdate { cur -> cur?.next } ?.value } @Test fun box() { val testClass = LockFreeStackTest() testClass.testClear() testClass.testPushPopLoop() testClass.testPushPopUpdate() }