Use FreezableAtomicReference in unhandled exception hook
This commit is contained in:
committed by
Space
parent
fe855d09d8
commit
455625bcee
@@ -6,7 +6,7 @@ import kotlin.test.*
|
|||||||
|
|
||||||
import kotlin.native.concurrent.*
|
import kotlin.native.concurrent.*
|
||||||
|
|
||||||
fun main(args : Array<String>) {
|
fun mainLegacyMM() {
|
||||||
assertFailsWith<InvalidMutabilityException> {
|
assertFailsWith<InvalidMutabilityException> {
|
||||||
setUnhandledExceptionHook { _ -> println("wrong") }
|
setUnhandledExceptionHook { _ -> println("wrong") }
|
||||||
}
|
}
|
||||||
@@ -19,4 +19,26 @@ fun main(args : Array<String>) {
|
|||||||
assertNull(old)
|
assertNull(old)
|
||||||
|
|
||||||
throw Error("an error")
|
throw Error("an error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun mainExperimentalMM() {
|
||||||
|
val unset = setUnhandledExceptionHook { _ -> println("ok") }
|
||||||
|
assertNull(unset)
|
||||||
|
|
||||||
|
val x = 42
|
||||||
|
val old = setUnhandledExceptionHook {
|
||||||
|
throwable: Throwable -> println("value $x: ${throwable::class.simpleName}")
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull(old)
|
||||||
|
|
||||||
|
throw Error("an error")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
if (Platform.memoryModel == MemoryModel.EXPERIMENTAL) {
|
||||||
|
mainExperimentalMM()
|
||||||
|
} else {
|
||||||
|
mainLegacyMM()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -379,6 +379,19 @@ public class FreezableAtomicReference<T>(private var value_: T) {
|
|||||||
public override fun toString(): String =
|
public override fun toString(): String =
|
||||||
"${debugString(this)} -> ${debugString(value)}"
|
"${debugString(this)} -> ${debugString(value)}"
|
||||||
|
|
||||||
|
// TODO: Consider making this public.
|
||||||
|
internal fun swap(new: T): T {
|
||||||
|
while (true) {
|
||||||
|
val old = value
|
||||||
|
if (old === new) {
|
||||||
|
return old
|
||||||
|
}
|
||||||
|
if (compareAndSet(old, new)) {
|
||||||
|
return old
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Implementation details.
|
// Implementation details.
|
||||||
@GCUnsafeCall("Kotlin_AtomicReference_set")
|
@GCUnsafeCall("Kotlin_AtomicReference_set")
|
||||||
private external fun setImpl(new: Any?): Unit
|
private external fun setImpl(new: Any?): Unit
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ package kotlin.native.internal
|
|||||||
|
|
||||||
import kotlin.internal.getProgressionLastElement
|
import kotlin.internal.getProgressionLastElement
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.native.concurrent.AtomicReference
|
import kotlin.native.concurrent.FreezableAtomicReference
|
||||||
|
import kotlin.native.concurrent.freeze
|
||||||
|
|
||||||
@ExportForCppRuntime
|
@ExportForCppRuntime
|
||||||
fun ThrowNullPointerException(): Nothing {
|
fun ThrowNullPointerException(): Nothing {
|
||||||
@@ -123,7 +124,12 @@ internal external fun TerminateWithUnhandledException(throwable: Throwable)
|
|||||||
// in a normal global initialization flow. This is important if some global happens
|
// in a normal global initialization flow. This is important if some global happens
|
||||||
// to throw an exception during it's initialization before this hook would've been initialized.
|
// to throw an exception during it's initialization before this hook would've been initialized.
|
||||||
internal object UnhandledExceptionHookHolder {
|
internal object UnhandledExceptionHookHolder {
|
||||||
internal val hook: AtomicReference<ReportUnhandledExceptionHook?> = AtomicReference(null)
|
internal val hook: FreezableAtomicReference<ReportUnhandledExceptionHook?> =
|
||||||
|
if (Platform.memoryModel == MemoryModel.EXPERIMENTAL) {
|
||||||
|
FreezableAtomicReference<ReportUnhandledExceptionHook?>(null)
|
||||||
|
} else {
|
||||||
|
FreezableAtomicReference<ReportUnhandledExceptionHook?>(null).freeze()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
|
|||||||
Reference in New Issue
Block a user