blob: 4a1cb5989f6d780c2e220d45d2b71da7631f0f54 [file] [log] [blame]
/*
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
package kotlinx.atomicfu
import java.util.concurrent.atomic.*
import kotlin.internal.*
@Suppress("FunctionName")
@InlineOnly
public actual fun Trace(size: Int, format: TraceFormat): TraceBase =
TraceImpl(size, format)
public actual fun TraceBase.named(name: String): TraceBase =
if (this === TraceBase.None) this else NamedTrace(this, name)
private fun getSystemProperty(key: String): String? =
try { System.getProperty(key) } catch (e: SecurityException) { null }
public actual val traceFormatDefault: TraceFormat =
if (getSystemProperty("kotlinx.atomicfu.trace.thread") != null) TraceFormatThread() else TraceFormat()
private class TraceFormatThread : TraceFormat() {
override fun format(index: Int, event: Any): String =
"$index: [${Thread.currentThread().name}] $event"
}
private class NamedTrace(
private val trace: TraceBase,
private val name: String
) : TraceBase() {
override fun append(event: Any) = trace.append("$name.$event")
override fun append(event1: Any, event2: Any) = trace.append("$name.$event1", "$name.$event2")
override fun append(event1: Any, event2: Any, event3: Any) =
trace.append("$name.$event1", "$name.$event2", "$name.$event3")
override fun append(event1: Any, event2: Any, event3: Any, event4: Any) =
trace.append("$name.$event1", "$name.$event2", "$name.$event3", "$name.$event4")
override fun toString(): String = trace.toString()
}
private class TraceImpl(size: Int, private val format: TraceFormat) : TraceBase() {
init { require(size >= 1) }
private val size = ((size shl 1) - 1).takeHighestOneBit() // next power of 2
private val mask = this.size - 1
private val trace = arrayOfNulls<Any>(this.size)
private val index = AtomicInteger(0)
override fun append(event: Any) {
val i = index.getAndIncrement()
trace[i and mask] = event
}
override fun append(event1: Any, event2: Any) {
val i = index.getAndAdd(2)
trace[i and mask] = event1
trace[(i + 1) and mask] = event2
}
override fun append(event1: Any, event2: Any, event3: Any) {
val i = index.getAndAdd(3)
trace[i and mask] = event1
trace[(i + 1) and mask] = event2
trace[(i + 2) and mask] = event3
}
override fun append(event1: Any, event2: Any, event3: Any, event4: Any) {
val i = index.getAndAdd(4)
trace[i and mask] = event1
trace[(i + 1) and mask] = event2
trace[(i + 2) and mask] = event3
trace[(i + 3) and mask] = event4
}
override fun toString(): String = buildString {
val index = index.get()
val start = index and mask
var i = if (index > size) index - size else 0
var pos = start
var cnt = 0
do {
val s = trace[pos]
if (s != null) {
if (cnt++ > 0) append('\n')
append(format.format(i, s))
i++
}
pos = (pos + 1) and mask
} while (pos != start)
}
}