Gross stdlib cleanup (part 2) (#1924)

This commit is contained in:
Nikolay Igotti
2018-08-24 10:14:10 +03:00
committed by GitHub
parent 6d4218c3af
commit 59eae5e04b
60 changed files with 135 additions and 165 deletions
+2 -2
View File
@@ -48,7 +48,7 @@ framework("MyCustomFramework") {
### Q: Why do I see `InvalidMutabilityException`? ### Q: Why do I see `InvalidMutabilityException`?
A: It likely happens, because you are trying to mutate a frozen object. Object could transfer to the A: It likely happens, because you are trying to mutate a frozen object. Object could transfer to the
frozen state either explicitly, as objects reachable from objects on which `konan.worker.freeze` is called, frozen state either explicitly, as objects reachable from objects on which `kotlin.native.concurrent.freeze` is called,
or implicitly (i.e. reachable from `enum` or global singleton object - see next question). or implicitly (i.e. reachable from `enum` or global singleton object - see next question).
@@ -56,7 +56,7 @@ or implicitly (i.e. reachable from `enum` or global singleton object - see next
A: Currently, singleton objects are immutable (i.e. frozen after creation), and it's generally considered A: Currently, singleton objects are immutable (i.e. frozen after creation), and it's generally considered
a good practise to have global state immutable. If for some reasons you need mutable state inside such an a good practise to have global state immutable. If for some reasons you need mutable state inside such an
object, use `@konan.ThreadLocal` annotation on the object. Also `konan.worker.AtomicReference` class could be object, use `@konan.ThreadLocal` annotation on the object. Also `kotlin.native.concurrent.AtomicReference` class could be
used to store different pointers to frozen objects in a frozen object and atomically update those. used to store different pointers to frozen objects in a frozen object and atomically update those.
### Q: How can I compile my project against Kotlin/Native master? ### Q: How can I compile my project against Kotlin/Native master?
+1 -1
View File
@@ -5,7 +5,7 @@ important invariant that object is either immutable or
accessible from the single thread at the moment (`mutable XOR global`). accessible from the single thread at the moment (`mutable XOR global`).
Immutability is the runtime property in Kotlin/Native, and can be applied Immutability is the runtime property in Kotlin/Native, and can be applied
to an arbitrary object subgraph using `konan.worker.freeze` function. to an arbitrary object subgraph using `kotlin.native.concurrent.freeze` function.
It makes all objects reachable from the given one immutable, and It makes all objects reachable from the given one immutable, and
such a transition is a one way operation (object cannot be unfrozen later). such a transition is a one way operation (object cannot be unfrozen later).
Some naturally immutable objects, such as `kotlin.String`, `kotlin.Int` and Some naturally immutable objects, such as `kotlin.String`, `kotlin.Int` and
@@ -79,12 +79,12 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns, vararg konanPrimitives:
val staticCFunction = packageScope.getContributedFunctions("staticCFunction").toSet() val staticCFunction = packageScope.getContributedFunctions("staticCFunction").toSet()
val workerPackageScope = builtIns.builtInsModule.getPackage(FqName("kotlin.native.worker")).memberScope val concurrentPackageScope = builtIns.builtInsModule.getPackage(FqName("kotlin.native.concurrent")).memberScope
val scheduleFunction = workerPackageScope.getContributedClass("Worker") val scheduleFunction = concurrentPackageScope.getContributedClass("Worker")
.unsubstitutedMemberScope.getContributedFunctions("schedule").single() .unsubstitutedMemberScope.getContributedFunctions("schedule").single()
val scheduleImplFunction = workerPackageScope.getContributedFunctions("scheduleImpl").single() val scheduleImplFunction = concurrentPackageScope.getContributedFunctions("scheduleImpl").single()
val signExtend = packageScope.getContributedFunctions("signExtend").single() val signExtend = packageScope.getContributedFunctions("signExtend").single()
@@ -297,10 +297,12 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
context.getInternalFunctions("valueOfForEnum").single()) context.getInternalFunctions("valueOfForEnum").single())
val enumValues = symbolTable.referenceSimpleFunction( val enumValues = symbolTable.referenceSimpleFunction(
builtInsPackage("kotlin").getContributedFunctions(Name.identifier("enumValues"), NoLookupLocation.FROM_BACKEND).single()) builtInsPackage("kotlin").getContributedFunctions(
Name.identifier("enumValues"), NoLookupLocation.FROM_BACKEND).single())
val enumValueOf = symbolTable.referenceSimpleFunction( val enumValueOf = symbolTable.referenceSimpleFunction(
builtInsPackage("kotlin").getContributedFunctions(Name.identifier("enumValueOf"), NoLookupLocation.FROM_BACKEND).single()) builtInsPackage("kotlin").getContributedFunctions(
Name.identifier("enumValueOf"), NoLookupLocation.FROM_BACKEND).single())
val createUninitializedInstance = symbolTable.referenceSimpleFunction( val createUninitializedInstance = symbolTable.referenceSimpleFunction(
context.getInternalFunctions("createUninitializedInstance").single()) context.getInternalFunctions("createUninitializedInstance").single())
@@ -309,14 +311,17 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
context.getInternalFunctions("initInstance").single()) context.getInternalFunctions("initInstance").single())
val freeze = symbolTable.referenceSimpleFunction( val freeze = symbolTable.referenceSimpleFunction(
builtInsPackage("kotlin", "native", "worker").getContributedFunctions(Name.identifier("freeze"), NoLookupLocation.FROM_BACKEND).single()) builtInsPackage("kotlin", "native", "concurrent").getContributedFunctions(
Name.identifier("freeze"), NoLookupLocation.FROM_BACKEND).single())
val println = symbolTable.referenceSimpleFunction( val println = symbolTable.referenceSimpleFunction(
builtInsPackage("kotlin", "io").getContributedFunctions(Name.identifier("println"), NoLookupLocation.FROM_BACKEND) builtInsPackage("kotlin", "io").getContributedFunctions(
Name.identifier("println"), NoLookupLocation.FROM_BACKEND)
.single { it.valueParameters.singleOrNull()?.type == builtIns.stringType }) .single { it.valueParameters.singleOrNull()?.type == builtIns.stringType })
val anyNToString = symbolTable.referenceSimpleFunction( val anyNToString = symbolTable.referenceSimpleFunction(
builtInsPackage("kotlin").getContributedFunctions(Name.identifier("toString"), NoLookupLocation.FROM_BACKEND) builtInsPackage("kotlin").getContributedFunctions(
Name.identifier("toString"), NoLookupLocation.FROM_BACKEND)
.single { it.extensionReceiverParameter?.type == builtIns.nullableAnyType}) .single { it.extensionReceiverParameter?.type == builtIns.nullableAnyType})
val getContinuation = symbolTable.referenceSimpleFunction( val getContinuation = symbolTable.referenceSimpleFunction(
@@ -350,10 +355,8 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
.filterNot { it.isExpect }.single().getter!! .filterNot { it.isExpect }.single().getter!!
) )
// removed in Big Kotlin @c62e4b4fcf50e99800e6d5c3a220101b691e1d43
val refClass = symbolTable.referenceClass(context.getInternalClass("Ref")) val refClass = symbolTable.referenceClass(context.getInternalClass("Ref"))
val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl) val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl)
val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedMutablePropertyImpl) val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedMutablePropertyImpl)
@@ -376,7 +379,7 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
symbolTable.referenceClass(context.getInternalClass(name)) symbolTable.referenceClass(context.getInternalClass(name))
private fun getKonanTestClass(className: String) = symbolTable.referenceClass( private fun getKonanTestClass(className: String) = symbolTable.referenceClass(
builtInsPackage("kotlin", "native", "test").getContributedClassifier( builtInsPackage("kotlin", "native", "internal", "test").getContributedClassifier(
Name.identifier(className), NoLookupLocation.FROM_BACKEND Name.identifier(className), NoLookupLocation.FROM_BACKEND
) as ClassDescriptor) ) as ClassDescriptor)
@@ -61,7 +61,7 @@ internal fun findMainEntryPoint(context: Context): FunctionDescriptor? {
} }
private val defaultEntryName = "main" private val defaultEntryName = "main"
private val testEntryName = "kotlin.native.test.main" private val testEntryName = "kotlin.native.internal.test.main"
private val defaultEntryPackage = FqName.ROOT private val defaultEntryPackage = FqName.ROOT
@@ -346,7 +346,7 @@ internal class TestProcessor (val context: KonanBackendContext) {
} }
/** /**
* Builds a method in `[testSuite]` class with anem `[getterName]` * Builds a method in `[testSuite]` class with name `[getterName]`
* returning a new instance of class referenced by [classSymbol]. * returning a new instance of class referenced by [classSymbol].
*/ */
private inner class InstanceGetterBuilder(val classSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name) private inner class InstanceGetterBuilder(val classSymbol: IrClassSymbol, testSuite: IrClassSymbol, getterName: Name)
@@ -1,7 +1,7 @@
package codegen.enum.isFrozen package codegen.enum.isFrozen
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
enum class Zzz(val zzz: String) { enum class Zzz(val zzz: String) {
Z1("z1"), Z1("z1"),
@@ -1,6 +1,6 @@
package runtime.basic.worker_random package runtime.basic.worker_random
import kotlin.native.worker.* import kotlin.native.concurrent.*
import kotlin.collections.* import kotlin.collections.*
import kotlin.random.* import kotlin.random.*
import kotlin.system.* import kotlin.system.*
@@ -2,7 +2,7 @@ package runtime.workers.atomic0
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
fun test1(workers: Array<Worker>) { fun test1(workers: Array<Worker>) {
val atomic = AtomicInt(15) val atomic = AtomicInt(15)
@@ -1,7 +1,7 @@
package runtime.workers.enum_identity package runtime.workers.enum_identity
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
enum class A { enum class A {
A, B A, B
@@ -18,7 +18,7 @@ package runtime.workers.freeze0
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
data class SharedDataMember(val double: Double) data class SharedDataMember(val double: Double)
@@ -18,7 +18,7 @@ package runtime.workers.freeze1
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
data class Node(var previous: Node?, var data: Int) data class Node(var previous: Node?, var data: Int)
@@ -18,7 +18,7 @@ package runtime.workers.freeze2
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
data class Data(var int: Int) data class Data(var int: Int)
@@ -2,7 +2,7 @@ package runtime.workers.freeze3
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
object Immutable { object Immutable {
var x = 1 var x = 1
@@ -2,7 +2,7 @@ package runtime.workers.freeze4
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
data class Data(val x: Int, val s: String, val next: Data? = null) data class Data(val x: Int, val s: String, val next: Data? = null)
@@ -1,6 +1,7 @@
package runtime.workers.freeze5 package runtime.workers.freeze5
import kotlin.test.* import kotlin.test.*
object Keys { object Keys {
internal val myMap: Map<String, List<String>> = mapOf( internal val myMap: Map<String, List<String>> = mapOf(
"val1" to listOf("a1", "a2", "a3"), "val1" to listOf("a1", "a2", "a3"),
@@ -2,7 +2,7 @@ package runtime.workers.freeze_stress
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
class Random(private var seed: Int) { class Random(private var seed: Int) {
fun next(): Int { fun next(): Int {
@@ -2,7 +2,7 @@ package runtime.workers.lazy0
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
data class Data(val x: Int, val y: String) data class Data(val x: Int, val y: String)
@@ -2,7 +2,7 @@ package runtime.workers.lazy1
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
class Leak { class Leak {
val leak by lazy { this } val leak by lazy { this }
@@ -2,11 +2,11 @@ package runtime.workers.worker0
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
@Test fun runTest() { @Test fun runTest() {
val worker = startWorker() val worker = startWorker()
val future = worker.schedule(TransferMode.CHECKED, { "Input".shallowCopy()}) { val future = worker.schedule(TransferMode.CHECKED, { "Input" }) {
input -> input + " processed" input -> input + " processed"
} }
future.consume { future.consume {
@@ -2,7 +2,7 @@ package runtime.workers.worker1
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
@Test fun runTest() { @Test fun runTest() {
val COUNT = 5 val COUNT = 5
@@ -10,7 +10,7 @@ import kotlin.native.worker.*
for (attempt in 1 .. 3) { for (attempt in 1 .. 3) {
val futures = Array(workers.size, val futures = Array(workers.size,
{ i -> workers[i].schedule(TransferMode.CHECKED, { "$attempt: Input $i".shallowCopy() }) { i -> workers[i].schedule(TransferMode.CHECKED, { "$attempt: Input $i" })
{ input -> input + " processed" } { input -> input + " processed" }
}) })
futures.forEachIndexed { index, future -> futures.forEachIndexed { index, future ->
@@ -2,7 +2,7 @@ package runtime.workers.worker2
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
data class WorkerArgument(val intParam: Int, val stringParam: String) data class WorkerArgument(val intParam: Int, val stringParam: String)
data class WorkerResult(val intResult: Int, val stringResult: String) data class WorkerResult(val intResult: Int, val stringResult: String)
@@ -2,7 +2,7 @@ package runtime.workers.worker3
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
data class DataParam(var int: Int) data class DataParam(var int: Int)
data class WorkerArgument(val intParam: Int, val dataParam: DataParam) data class WorkerArgument(val intParam: Int, val dataParam: DataParam)
@@ -2,7 +2,7 @@ package runtime.workers.worker4
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
@Test fun runTest() { @Test fun runTest() {
val worker = startWorker() val worker = startWorker()
@@ -2,11 +2,11 @@ package runtime.workers.worker5
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
@Test fun runTest() { @Test fun runTest() {
val worker = startWorker() val worker = startWorker()
val future = worker.schedule(TransferMode.CHECKED, { "zzz".shallowCopy() }) { val future = worker.schedule(TransferMode.CHECKED, { "zzz" }) {
input -> input.length input -> input.length
} }
future.consume { future.consume {
@@ -2,7 +2,7 @@ package runtime.workers.worker6
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
@Test fun runTest() { @Test fun runTest() {
val worker = startWorker() val worker = startWorker()
@@ -2,11 +2,11 @@ package runtime.workers.worker7
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
@Test fun runTest() { @Test fun runTest() {
val worker = startWorker() val worker = startWorker()
val future = worker.schedule(TransferMode.CHECKED, { "Input".shallowCopy() }) { val future = worker.schedule(TransferMode.CHECKED, { "Input" }) {
input -> println(input) input -> println(input)
} }
future.consume { future.consume {
@@ -2,7 +2,7 @@ package runtime.workers.worker8
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
data class SharedDataMember(val double: Double) data class SharedDataMember(val double: Double)
@@ -2,7 +2,7 @@ package runtime.workers.worker9
import kotlin.test.* import kotlin.test.*
import kotlin.native.worker.* import kotlin.native.concurrent.*
@Test fun runTest() { @Test fun runTest() {
withLock { println("zzz") } withLock { println("zzz") }
+1 -2
View File
@@ -1,8 +1,7 @@
package kotlin.test.tests package kotlin.test.tests
import kotlin.test.* import kotlin.test.*
import kotlin.native.test.* import kotlin.native.internal.test.*
@Ignore @Ignore
class IgnoredClass { class IgnoredClass {
+1 -1
View File
@@ -1,7 +1,7 @@
package kotlin.test.tests package kotlin.test.tests
import kotlin.test.* import kotlin.test.*
import kotlin.native.test.* import kotlin.native.internal.test.*
@Test @Test
fun test() { fun test() {
-28
View File
@@ -415,25 +415,6 @@ KInt schedule(KInt id, KInt transferMode, KRef producer, KNativePtr jobFunction)
return future->id(); return future->id();
} }
OBJ_GETTER(shallowCopy, KConstRef object) {
if (object == nullptr) RETURN_OBJ(nullptr);
const TypeInfo* typeInfo = object->type_info();
bool isArray = typeInfo->instanceSize_ < 0;
KRef result = isArray ?
AllocArrayInstance(typeInfo, object->array()->count_, OBJ_RESULT) :
AllocInstance(typeInfo, OBJ_RESULT);
// TODO: what to do when object references exist.
if (isArray) {
RuntimeAssert(object->array()->count_ == 0 || typeInfo != theArrayTypeInfo, "Object array copy unimplemented");
memcpy(result->array() + 1, object->array() + 1, ArrayDataSizeBytes(object->array()));
} else {
RuntimeAssert(typeInfo->objOffsetsCount_ == 0, "Object reference copy unimplemented");
memcpy(result + 1, object + 1, typeInfo->instanceSize_);
}
return result;
}
KInt stateOfFuture(KInt id) { KInt stateOfFuture(KInt id) {
return theState()->stateOfFutureUnlocked(id); return theState()->stateOfFutureUnlocked(id);
} }
@@ -477,11 +458,6 @@ KInt startWorker() {
return -1; return -1;
} }
OBJ_GETTER(shallowCopy, KConstRef object) {
ThrowWorkerUnsupported();
RETURN_OBJ(nullptr);
}
KInt stateOfFuture(KInt id) { KInt stateOfFuture(KInt id) {
ThrowWorkerUnsupported(); ThrowWorkerUnsupported();
return 0; return 0;
@@ -540,10 +516,6 @@ KInt Kotlin_Worker_scheduleInternal(KInt id, KInt transferMode, KRef producer, K
return schedule(id, transferMode, producer, job); return schedule(id, transferMode, producer, job);
} }
OBJ_GETTER(Kotlin_Worker_shallowCopyInternal, KConstRef object) {
RETURN_RESULT_OF(shallowCopy, object);
}
KInt Kotlin_Worker_stateOfFuture(KInt id) { KInt Kotlin_Worker_stateOfFuture(KInt id) {
return stateOfFuture(id); return stateOfFuture(id);
} }
+2 -1
View File
@@ -19,7 +19,8 @@ package kotlin
/** /**
* A vector of bits growing if necessary and allowing one to set/clear/read bits from it by a bit index. * A vector of bits growing if necessary and allowing one to set/clear/read bits from it by a bit index.
*/ */
class BitSet(size: Int = ELEMENT_SIZE) { // TODO: make me internal!
public class BitSet(size: Int = ELEMENT_SIZE) {
companion object { companion object {
// Size of one element in the array used to store bits. // Size of one element in the array used to store bits.
+3 -2
View File
@@ -16,8 +16,9 @@
package kotlin package kotlin
import kotlin.reflect.KProperty import kotlin.native.concurrent.FreezeAwareLazyImpl
import kotlin.native.internal.FixmeConcurrency import kotlin.native.internal.FixmeConcurrency
import kotlin.reflect.KProperty
/** /**
* Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
@@ -28,7 +29,7 @@ import kotlin.native.internal.FixmeConcurrency
* Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on * Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on
* the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future. * the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future.
*/ */
public actual fun <T> lazy(initializer: () -> T): Lazy<T> = kotlin.native.worker.FreezeAwareLazyImpl(initializer) public actual fun <T> lazy(initializer: () -> T): Lazy<T> = FreezeAwareLazyImpl(initializer)
/** /**
* Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
+5 -3
View File
@@ -1182,7 +1182,8 @@ public final class Float private constructor(private val value: kotlin.native.in
} }
@SymbolName("Kotlin_Float_bits") @SymbolName("Kotlin_Float_bits")
external public fun bits(): Int @PublishedApi
external internal fun bits(): Int
} }
/** /**
@@ -1398,10 +1399,11 @@ public final class Double private constructor(private val value: kotlin.native.i
public override fun equals(other: Any?): Boolean = other is Double && this.equals(other) public override fun equals(other: Any?): Boolean = other is Double && this.equals(other)
public override fun toString() = NumberConverter.convert(this) public override fun toString(): String = NumberConverter.convert(this)
public override fun hashCode(): Int = bits().hashCode() public override fun hashCode(): Int = bits().hashCode()
@SymbolName("Kotlin_Double_bits") @SymbolName("Kotlin_Double_bits")
external public fun bits(): Long @PublishedApi
external internal fun bits(): Long
} }
@@ -16,7 +16,7 @@
package kotlin.collections package kotlin.collections
import kotlin.native.worker.isFrozen import kotlin.native.concurrent.isFrozen
actual class HashMap<K, V> private constructor( actual class HashMap<K, V> private constructor(
private var keysArray: Array<K>, private var keysArray: Array<K>,
@@ -16,7 +16,7 @@
package kotlin.collections package kotlin.collections
fun Int.highestOneBit() : Int { internal fun Int.highestOneBit() : Int {
var index = 31 var index = 31
while (index >= 0) { while (index >= 0) {
@@ -29,7 +29,7 @@ fun Int.highestOneBit() : Int {
return 0 return 0
} }
fun Int.numberOfLeadingZeros() : Int { internal fun Int.numberOfLeadingZeros() : Int {
var index = 31 var index = 31
while (index >= 0) { while (index >= 0) {
@@ -27,4 +27,4 @@ actual annotation class JvmMultifileClass
actual annotation class JvmField actual annotation class JvmField
@Target(AnnotationTarget.FIELD) @Target(AnnotationTarget.FIELD)
actual annotation class Volatile actual annotation class Volatile
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.worker package kotlin.native.concurrent
import kotlin.native.internal.Frozen import kotlin.native.internal.Frozen
import kotlin.native.internal.NoReorderFields import kotlin.native.internal.NoReorderFields
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.worker package kotlin.native.concurrent
import kotlin.native.internal.ExportForCppRuntime import kotlin.native.internal.ExportForCppRuntime
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.worker package kotlin.native.concurrent
import kotlin.native.SymbolName import kotlin.native.SymbolName
import kotlin.native.internal.ExportForCppRuntime import kotlin.native.internal.ExportForCppRuntime
@@ -40,12 +40,11 @@ enum class FutureState(val value: Int) {
/** /**
* Class representing abstract computation, whose result may become available in the future. * Class representing abstract computation, whose result may become available in the future.
*/ */
// TODO: make me value class! public inline class Future<T>(val id: FutureId) {
class Future<T> internal constructor(val id: FutureId) {
/** /**
* Blocks execution until the future is ready. * Blocks execution until the future is ready.
*/ */
inline fun <R> consume(code: (T) -> R) = public inline fun <R> consume(code: (T) -> R): R =
when (state) { when (state) {
FutureState.SCHEDULED, FutureState.COMPUTED -> { FutureState.SCHEDULED, FutureState.COMPUTED -> {
val value = @Suppress("UNCHECKED_CAST", "NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") (consumeFuture(id) as T) val value = @Suppress("UNCHECKED_CAST", "NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") (consumeFuture(id) as T)
@@ -57,21 +56,21 @@ class Future<T> internal constructor(val id: FutureId) {
throw IllegalStateException("Future is cancelled") throw IllegalStateException("Future is cancelled")
} }
fun result(): T = consume { it -> it } public fun result(): T = consume { it -> it }
val state: FutureState public val state: FutureState
get() = FutureState.values()[stateOfFuture(id)] get() = FutureState.values()[stateOfFuture(id)]
override fun equals(other: Any?) = (other is Future<*>) && (id == other.id) public override fun equals(other: Any?): Boolean = (other is Future<*>) && (id == other.id)
override fun hashCode() = id public override fun hashCode(): Int = id
} }
/** /**
* Wait for availability of futures in the collection. Returns set with all futures which have * Wait for availability of futures in the collection. Returns set with all futures which have
* value available for the consumption. * value available for the consumption.
*/ */
fun <T> Collection<Future<T>>.waitForMultipleFutures(millis: Int): Set<Future<T>> { public fun <T> Collection<Future<T>>.waitForMultipleFutures(millis: Int): Set<Future<T>> {
val result = mutableSetOf<Future<T>>() val result = mutableSetOf<Future<T>>()
while (true) { while (true) {
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.worker package kotlin.native.concurrent
import kotlin.native.internal.NoReorderFields import kotlin.native.internal.NoReorderFields
@@ -65,7 +65,9 @@ internal class FreezeAwareLazyImpl<out T>(initializer: () -> T) : Lazy<T> {
} }
} }
// Racy! /**
* This operation on shared objects may return value which is no longer reflect the current state of lazy.
*/
override fun isInitialized(): Boolean = (value_ !== UNINITIALIZED) && (value_ !== INITIALIZING) override fun isInitialized(): Boolean = (value_ !== UNINITIALIZED) && (value_ !== INITIALIZING)
override fun toString(): String = if (isInitialized()) override fun toString(): String = if (isInitialized())
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.worker package kotlin.native.concurrent
import kotlin.native.internal.Frozen import kotlin.native.internal.Frozen
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.worker package kotlin.native.concurrent
import kotlinx.cinterop.* import kotlinx.cinterop.*
@@ -46,17 +46,6 @@ enum class TransferMode(val value: Int) {
UNCHECKED(1) // USE UNCHECKED MODE ONLY IF ABSOLUTELY SURE WHAT YOU'RE DOING!!! UNCHECKED(1) // USE UNCHECKED MODE ONLY IF ABSOLUTELY SURE WHAT YOU'RE DOING!!!
} }
/**
* Creates verbatim *shallow* copy of passed object, use carefully to create disjoint object graph.
*/
inline fun <reified T> T.shallowCopy(): T = shallowCopyInternal(this) as T
/**
* Creates verbatim *deep* copy of passed object's graph, use *VERY* carefully to create disjoint object graph.
* Note that this function could potentially duplicate a lot of objects.
*/
inline fun <reified T> T.deepCopy(): T = TODO()
/** /**
* Creates stable pointer to object, ensuring associated object subgraph is disjoint in specified mode * Creates stable pointer to object, ensuring associated object subgraph is disjoint in specified mode
* ([TransferMode.CHECKED] by default). * ([TransferMode.CHECKED] by default).
@@ -75,11 +64,9 @@ inline fun <reified T> attachObjectGraph(stable: COpaquePointer?): T =
// Private APIs. // Private APIs.
@PublishedApi @PublishedApi
@SymbolName("Kotlin_Worker_shallowCopyInternal")
external internal fun shallowCopyInternal(value: Any?): Any?
@PublishedApi
@SymbolName("Kotlin_Worker_detachObjectGraphInternal") @SymbolName("Kotlin_Worker_detachObjectGraphInternal")
external internal fun detachObjectGraphInternal(mode: Int, producer: () -> Any?): COpaquePointer? external internal fun detachObjectGraphInternal(mode: Int, producer: () -> Any?): COpaquePointer?
@PublishedApi @PublishedApi
@SymbolName("Kotlin_Worker_attachObjectGraphInternal") @SymbolName("Kotlin_Worker_attachObjectGraphInternal")
external internal fun attachObjectGraphInternal(stable: COpaquePointer?): Any? external internal fun attachObjectGraphInternal(stable: COpaquePointer?): Any?
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.worker package kotlin.native.concurrent
import kotlin.native.SymbolName import kotlin.native.SymbolName
import kotlin.native.internal.ExportForCppRuntime import kotlin.native.internal.ExportForCppRuntime
@@ -42,12 +42,12 @@ typealias WorkerId = Int
* Class representing worker. * Class representing worker.
*/ */
// TODO: make me value class! // TODO: make me value class!
class Worker(val id: WorkerId) { public class Worker(val id: WorkerId) {
/** /**
* Requests termination of the worker. `processScheduledJobs` controls is we shall wait * Requests termination of the worker. `processScheduledJobs` controls is we shall wait
* until all scheduled jobs processed, or terminate immediately. * until all scheduled jobs processed, or terminate immediately.
*/ */
fun requestTermination(processScheduledJobs: Boolean = true) = public fun requestTermination(processScheduledJobs: Boolean = true) =
Future<Nothing?>(requestTerminationInternal(id, processScheduledJobs)) Future<Nothing?>(requestTerminationInternal(id, processScheduledJobs))
/** /**
@@ -61,7 +61,7 @@ class Worker(val id: WorkerId) {
* the future, can use result of worker's computations. * the future, can use result of worker's computations.
*/ */
@Suppress("UNUSED_PARAMETER") @Suppress("UNUSED_PARAMETER")
fun <T1, T2> schedule(mode: TransferMode, producer: () -> T1, @VolatileLambda job: (T1) -> T2): Future<T2> = public fun <T1, T2> schedule(mode: TransferMode, producer: () -> T1, @VolatileLambda job: (T1) -> T2): Future<T2> =
/** /**
* This function is a magical operation, handled by lowering in the compiler, and replaced with call to * This function is a magical operation, handled by lowering in the compiler, and replaced with call to
* scheduleImpl(worker, mode, producer, job) * scheduleImpl(worker, mode, producer, job)
@@ -69,9 +69,9 @@ class Worker(val id: WorkerId) {
*/ */
throw RuntimeException("Shall not be called directly") throw RuntimeException("Shall not be called directly")
override fun equals(other: Any?) = (other is Worker) && (id == other.id) override public fun equals(other: Any?): Boolean = (other is Worker) && (id == other.id)
override fun hashCode() = id override public fun hashCode(): Int = id
} }
/** /**
@@ -79,7 +79,7 @@ class Worker(val id: WorkerId) {
* Typically new worker may be needed for computations offload to another core, for IO it may be * Typically new worker may be needed for computations offload to another core, for IO it may be
* better to use non-blocking IO combined with more lightweight coroutines. * better to use non-blocking IO combined with more lightweight coroutines.
*/ */
fun startWorker(): Worker = Worker(startInternal()) public fun startWorker(): Worker = Worker(startInternal())
// Private APIs. // Private APIs.
@kotlin.native.internal.ExportForCompiler @kotlin.native.internal.ExportForCompiler
@@ -14,9 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.test package kotlin.native.internal.test
class GTestLogger : TestLoggerWithStatistics() { internal class GTestLogger : TestLoggerWithStatistics() {
private val Collection<TestSuite>.totalTestsNotIgnored: Int private val Collection<TestSuite>.totalTestsNotIgnored: Int
get() = asSequence().filter { !it.ignored }.sumBy { it.testCases.values.count { !it.ignored } } get() = asSequence().filter { !it.ignored }.sumBy { it.testCases.values.count { !it.ignored } }
@@ -14,14 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.test package kotlin.native.internal.test
import kotlin.system.exitProcess import kotlin.system.exitProcess
@ThreadLocal @ThreadLocal
private val _generatedSuites = mutableListOf<TestSuite>() private val _generatedSuites = mutableListOf<TestSuite>()
internal fun registerSuite(suite: TestSuite): Unit { public fun registerSuite(suite: TestSuite): Unit {
_generatedSuites.add(suite) _generatedSuites.add(suite)
} }
@@ -14,11 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.test package kotlin.native.internal.test
import kotlin.text.StringBuilder import kotlin.text.StringBuilder
class TeamCityLogger : BaseTestLogger() { internal class TeamCityLogger : BaseTestLogger() {
private fun String.escapeForTC(): String = StringBuilder(length).apply { private fun String.escapeForTC(): String = StringBuilder(length).apply {
for(char in this@escapeForTC) { for(char in this@escapeForTC) {
@@ -14,9 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.test package kotlin.native.internal.test
interface TestListener { internal interface TestListener {
fun startTesting(runner: TestRunner) fun startTesting(runner: TestRunner)
fun finishTesting(runner: TestRunner, timeMillis: Long) fun finishTesting(runner: TestRunner, timeMillis: Long)
@@ -33,7 +33,7 @@ interface TestListener {
fun ignore(testCase: TestCase) fun ignore(testCase: TestCase)
} }
open class BaseTestListener: TestListener { internal open class BaseTestListener: TestListener {
override fun startTesting(runner: TestRunner) {} override fun startTesting(runner: TestRunner) {}
override fun finishTesting(runner: TestRunner, timeMillis: Long) {} override fun finishTesting(runner: TestRunner, timeMillis: Long) {}
override fun startIteration(runner: TestRunner, iteration: Int, suites: Collection<TestSuite>) {} override fun startIteration(runner: TestRunner, iteration: Int, suites: Collection<TestSuite>) {}
@@ -14,14 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.test package kotlin.native.internal.test
interface TestLogger: TestListener { internal interface TestLogger: TestListener {
fun logTestList(runner: TestRunner, suites: Collection<TestSuite>) fun logTestList(runner: TestRunner, suites: Collection<TestSuite>)
fun log(message: String) fun log(message: String)
} }
open class BaseTestLogger: BaseTestListener(), TestLogger { internal open class BaseTestLogger: BaseTestListener(), TestLogger {
override fun log(message: String) = println(message) override fun log(message: String) = println(message)
override fun logTestList(runner: TestRunner, suites: Collection<TestSuite>) { override fun logTestList(runner: TestRunner, suites: Collection<TestSuite>) {
suites.forEach { suite -> suites.forEach { suite ->
@@ -33,7 +33,7 @@ open class BaseTestLogger: BaseTestListener(), TestLogger {
} }
} }
open class TestLoggerWithStatistics: BaseTestLogger() { internal open class TestLoggerWithStatistics: BaseTestLogger() {
protected val statistics = MutableTestStatistics() protected val statistics = MutableTestStatistics()
@@ -46,13 +46,13 @@ open class TestLoggerWithStatistics: BaseTestLogger() {
override fun ignore(testCase: TestCase) = statistics.registerIgnore() override fun ignore(testCase: TestCase) = statistics.registerIgnore()
} }
class SilentTestLogger: BaseTestLogger() { internal class SilentTestLogger: BaseTestLogger() {
override fun logTestList(runner: TestRunner, suites: Collection<TestSuite>) {} override fun logTestList(runner: TestRunner, suites: Collection<TestSuite>) {}
override fun log(message: String) {} override fun log(message: String) {}
override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) = e.printStackTrace() override fun fail(testCase: TestCase, e: Throwable, timeMillis: Long) = e.printStackTrace()
} }
class SimpleTestLogger: BaseTestLogger() { internal class SimpleTestLogger: BaseTestLogger() {
override fun startTesting(runner: TestRunner) = println("Starting testing") override fun startTesting(runner: TestRunner) = println("Starting testing")
override fun finishTesting(runner: TestRunner, timeMillis: Long) = println("Testing finished") override fun finishTesting(runner: TestRunner, timeMillis: Long) = println("Testing finished")
@@ -14,14 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.test package kotlin.native.internal.test
import kotlin.IllegalArgumentException import kotlin.IllegalArgumentException
import kotlin.system.getTimeMillis import kotlin.system.getTimeMillis
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
import kotlin.text.StringBuilder import kotlin.text.StringBuilder
class TestRunner(val suites: List<TestSuite>, args: Array<String>) { internal class TestRunner(val suites: List<TestSuite>, args: Array<String>) {
private val filters = mutableListOf<(TestCase) -> Boolean>() private val filters = mutableListOf<(TestCase) -> Boolean>()
private val listeners = mutableSetOf<TestListener>() private val listeners = mutableSetOf<TestListener>()
private var logger: TestLogger = GTestLogger() private var logger: TestLogger = GTestLogger()
@@ -14,9 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.test package kotlin.native.internal.test
interface TestStatistics { internal interface TestStatistics {
val total: Int val total: Int
val passed: Int val passed: Int
val failed: Int val failed: Int
@@ -28,7 +28,7 @@ interface TestStatistics {
val hasFailedTests: Boolean val hasFailedTests: Boolean
} }
class MutableTestStatistics: TestStatistics { internal class MutableTestStatistics: TestStatistics {
override var total: Int = 0; private set override var total: Int = 0; private set
override var passed: Int = 0; private set override var passed: Int = 0; private set
@@ -14,13 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package kotlin.native.test package kotlin.native.internal.test
import kotlin.IllegalArgumentException import kotlin.IllegalArgumentException
import kotlin.system.getTimeMillis import kotlin.system.getTimeMillis
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
interface TestCase { public interface TestCase {
val name: String val name: String
val ignored: Boolean val ignored: Boolean
val suite: TestSuite val suite: TestSuite
@@ -30,7 +30,7 @@ interface TestCase {
internal val TestCase.prettyName get() = "${suite.name}.$name" internal val TestCase.prettyName get() = "${suite.name}.$name"
interface TestSuite { public interface TestSuite {
val name: String val name: String
val ignored: Boolean val ignored: Boolean
val testCases: Map<String, TestCase> val testCases: Map<String, TestCase>
@@ -40,14 +40,14 @@ interface TestSuite {
fun doAfterClass() fun doAfterClass()
} }
enum class TestFunctionKind { public enum class TestFunctionKind {
BEFORE_EACH, BEFORE_EACH,
AFTER_EACH, AFTER_EACH,
BEFORE_CLASS, BEFORE_CLASS,
AFTER_CLASS AFTER_CLASS
} }
abstract class AbstractTestSuite<F: Function<Unit>>(override val name: String, override val ignored: Boolean) public abstract class AbstractTestSuite<F: Function<Unit>>(override val name: String, override val ignored: Boolean)
: TestSuite { : TestSuite {
override fun toString(): String = name override fun toString(): String = name
@@ -80,7 +80,7 @@ abstract class AbstractTestSuite<F: Function<Unit>>(override val name: String, o
get() = testCases.size get() = testCases.size
} }
abstract class BaseClassSuite<INSTANCE, COMPANION>(name: String, ignored: Boolean) public abstract class BaseClassSuite<INSTANCE, COMPANION>(name: String, ignored: Boolean)
: AbstractTestSuite<INSTANCE.() -> Unit>(name, ignored) { : AbstractTestSuite<INSTANCE.() -> Unit>(name, ignored) {
class TestCase<INSTANCE, COMPANION>(name: String, class TestCase<INSTANCE, COMPANION>(name: String,
@@ -145,7 +145,7 @@ abstract class BaseClassSuite<INSTANCE, COMPANION>(name: String, ignored: Boolea
private typealias TopLevelFun = () -> Unit private typealias TopLevelFun = () -> Unit
class TopLevelSuite(name: String): AbstractTestSuite<TopLevelFun>(name, false) { public class TopLevelSuite(name: String): AbstractTestSuite<TopLevelFun>(name, false) {
class TestCase(name: String, override val suite: TopLevelSuite, testFunction: TopLevelFun, ignored: Boolean) class TestCase(name: String, override val suite: TopLevelSuite, testFunction: TopLevelFun, ignored: Boolean)
: BasicTestCase<TopLevelFun>(name, suite, testFunction, ignored) { : BasicTestCase<TopLevelFun>(name, suite, testFunction, ignored) {
@@ -21,7 +21,7 @@ package kotlin.native.ref
* retrieve a strong reference to an object, or return null, if object was already destoyed by * retrieve a strong reference to an object, or return null, if object was already destoyed by
* the memory manager. * the memory manager.
*/ */
class WeakReference<T : Any> { public class WeakReference<T : Any> {
/** /**
* Creates a weak reference object pointing to an object. Weak reference doesn't prevent * Creates a weak reference object pointing to an object. Weak reference doesn't prevent
* removing object, and is nullified once object is collected. * removing object, and is nullified once object is collected.
@@ -42,9 +42,10 @@ class WeakReference<T : Any> {
public fun clear() { public fun clear() {
pointer = null pointer = null
} }
/**
* Returns either reference to an object or null, if it was collected.
*/
public fun get(): T? = pointer?.get() as T?
} }
/**
* Returns either reference to an object or null, if it was collected.
*/
public inline fun <reified T : Any> WeakReference<T>.get() = pointer?.get() as T?
@@ -15,7 +15,7 @@
*/ */
package kotlin.random package kotlin.random
import kotlin.native.worker.AtomicLong import kotlin.native.concurrent.AtomicLong
import kotlin.system.getTimeNanos import kotlin.system.getTimeNanos
abstract class NativeRandom { abstract class NativeRandom {
@@ -33,10 +33,9 @@
package kotlin.text.regex package kotlin.text.regex
import kotlin.native.worker.AtomicReference
import kotlin.collections.associate import kotlin.collections.associate
import kotlin.native.worker.freeze import kotlin.native.concurrent.AtomicReference
import kotlin.native.concurrent.freeze
/** /**
* Unicode category (i.e. Ll, Lu). * Unicode category (i.e. Ll, Lu).
@@ -15,9 +15,10 @@
*/ */
import global.* import global.*
import kotlin.native.concurrent.*
import kotlinx.cinterop.* import kotlinx.cinterop.*
import platform.posix.* import platform.posix.*
import kotlin.native.worker.*
inline fun Int.ensureUnixCallResult(op: String, predicate: (Int) -> Boolean = { x -> x == 0} ): Int { inline fun Int.ensureUnixCallResult(op: String, predicate: (Int) -> Boolean = { x -> x == 0} ): Int {
if (!predicate(this)) { if (!predicate(this)) {
@@ -49,7 +50,7 @@ fun main(args: Array<String>) {
sharedData.f = 0.5f sharedData.f = 0.5f
sharedData.string = "Hello Kotlin!".cstr.getPointer(arena) sharedData.string = "Hello Kotlin!".cstr.getPointer(arena)
// Here we create detached mutable object, which could be later reattached by another thread. // Here we create detached mutable object, which could be later reattached by another thread.
sharedData.kotlinObject = kotlin.native.worker.detachObjectGraph { sharedData.kotlinObject = detachObjectGraph {
SharedData("A string", 42, SharedDataMember(2.39)) SharedData("A string", 42, SharedDataMember(2.39))
} }
// Here we create shared frozen object reference, // Here we create shared frozen object reference,
@@ -66,12 +67,12 @@ fun main(args: Array<String>) {
argC -> argC ->
initRuntimeIfNeeded() initRuntimeIfNeeded()
dumpShared("thread2") dumpShared("thread2")
val kotlinObject = kotlin.native.worker.attachObjectGraph<SharedData>(sharedData.kotlinObject) val kotlinObject = attachObjectGraph<SharedData>(sharedData.kotlinObject)
val arg = kotlin.native.worker.attachObjectGraph<SharedDataMember>(argC) val arg = attachObjectGraph<SharedDataMember>(argC)
println("thread arg is $arg Kotlin object is $kotlinObject frozen is $globalObject") println("thread arg is $arg Kotlin object is $kotlinObject frozen is $globalObject")
// Workaround for compiler issue. // Workaround for compiler issue.
null as COpaquePointer? null as COpaquePointer?
}, kotlin.native.worker.detachObjectGraph { SharedDataMember(3.14)} ).ensureUnixCallResult("pthread_create") }, detachObjectGraph { SharedDataMember(3.14)} ).ensureUnixCallResult("pthread_create")
pthread_join(thread.value, null).ensureUnixCallResult("pthread_join") pthread_join(thread.value, null).ensureUnixCallResult("pthread_join")
} }
+4 -2
View File
@@ -1,3 +1,5 @@
import kotlin.native.concurrent.attachObjectGraph
import kotlin.native.concurrent.detachObjectGraph
import kotlinx.cinterop.* import kotlinx.cinterop.*
import platform.AppKit.* import platform.AppKit.*
import platform.Foundation.* import platform.Foundation.*
@@ -30,12 +32,12 @@ private class Controller : NSObject() {
@ObjCAction @ObjCAction
fun onClick() { fun onClick() {
// Execute some async action on button click. // Execute some async action on button click.
dispatch_async_f(asyncQueue, kotlin.native.worker.detachObjectGraph { dispatch_async_f(asyncQueue, detachObjectGraph {
Data(clock_gettime_nsec_np(CLOCK_REALTIME)) Data(clock_gettime_nsec_np(CLOCK_REALTIME))
}, staticCFunction { }, staticCFunction {
it -> it ->
initRuntimeIfNeeded() initRuntimeIfNeeded()
val data = kotlin.native.worker.attachObjectGraph<Data>(it) val data = attachObjectGraph<Data>(it)
println("in async: $data") println("in async: $data")
}) })
} }
@@ -15,8 +15,8 @@
*/ */
import ffmpeg.* import ffmpeg.*
import kotlin.native.concurrent.*
import kotlinx.cinterop.* import kotlinx.cinterop.*
import kotlin.native.worker.*
import platform.posix.memcpy import platform.posix.memcpy
// This global variable only set to != null value in the decoding worker. // This global variable only set to != null value in the decoding worker.
@@ -329,7 +329,7 @@ class DecoderWorker : Disposable {
// All the real state must be stored on the worker's side. // All the real state must be stored on the worker's side.
private val worker: Worker private val worker: Worker
constructor() { worker = kotlin.native.worker.startWorker() } constructor() { worker = startWorker() }
constructor(id: WorkerId) { worker = Worker(id) } constructor(id: WorkerId) { worker = Worker(id) }
override fun dispose() { override fun dispose() {
+1 -1
View File
@@ -1,4 +1,4 @@
import kotlin.native.worker.* import kotlin.native.concurrent.*
data class WorkerArgument(val intParam: Int, val stringParam: String) data class WorkerArgument(val intParam: Int, val stringParam: String)
data class WorkerResult(val intResult: Int, val stringResult: String) data class WorkerResult(val intResult: Int, val stringResult: String)