package ru.dbotthepony.kstarbound import it.unimi.dsi.fastutil.ints.IntIterators import it.unimi.dsi.fastutil.objects.ObjectIterators interface ILoadingLog : Iterable { interface ILine { var text: String val progress: Float get() = if (maxElements > 0) elements.toFloat() / maxElements.toFloat() else 0f var elements: Int var maxElements: Int } fun line(text: String): ILine companion object : ILoadingLog, ILine { override var text: String get() = "" set(value) {} override var elements: Int get() = 0 set(value) {} override var maxElements: Int get() = 0 set(value) {} override fun line(text: String): ILine { return this } override fun iterator(): Iterator { return ObjectIterators.emptyIterator() } } } class LoadingLog : ILoadingLog { private val lines = arrayOfNulls(128) private var index = 0 private val lock = Any() private var size = 0 var lastActivity: Long = System.nanoTime() private set override fun line(text: String): ILoadingLog.ILine { return Line(text) } inner class Line(text: String) : ILoadingLog.ILine { override var text: String = text set(value) { field = value lastActivity = System.nanoTime() } @Volatile override var elements: Int = 0 override var maxElements: Int = 0 init { lastActivity = System.nanoTime() synchronized(lock) { lines[index++ and 127] = this size = (size + 1).coerceAtMost(127) } } } override fun iterator(): Iterator { return object : Iterator { private val index = (this@LoadingLog.index - 1) and 127 private val parent = IntIterators.fromTo(0, size) override fun hasNext(): Boolean { return parent.hasNext() } override fun next(): ILoadingLog.ILine { return lines[(index - parent.nextInt()) and 127]!! } } } }