Move everything under kotlin-native folder
I was forced to manually do update the following files, because otherwise they would be ignored according .gitignore settings. Probably they should be deleted from repo. Interop/.idea/compiler.xml Interop/.idea/gradle.xml Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_1_0_3.xml Interop/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_1_0_3.xml Interop/.idea/modules.xml Interop/.idea/modules/Indexer/Indexer.iml Interop/.idea/modules/Runtime/Runtime.iml Interop/.idea/modules/StubGenerator/StubGenerator.iml backend.native/backend.native.iml backend.native/bc.frontend/bc.frontend.iml backend.native/cli.bc/cli.bc.iml backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.kt backend.native/tests/link/lib/foo.kt backend.native/tests/link/lib/foo2.kt backend.native/tests/teamcity-test.property
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# Shared global state
|
||||
|
||||
This example shows how one could implement global shared state using interop mechanisms.
|
||||
|
||||
To build use `../gradlew assemble`.
|
||||
|
||||
To run use `../gradlew runReleaseExecutableGlobalState` or execute the program directly:
|
||||
|
||||
./build/bin/globalState/main/release/executable/globalState.kexe
|
||||
@@ -0,0 +1,27 @@
|
||||
plugins {
|
||||
kotlin("multiplatform")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
// Determine host preset.
|
||||
val hostOs = System.getProperty("os.name")
|
||||
|
||||
// Create target for the host platform.
|
||||
val hostTarget = when {
|
||||
hostOs == "Mac OS X" -> macosX64("globalState")
|
||||
hostOs == "Linux" -> linuxX64("globalState")
|
||||
hostOs.startsWith("Windows") -> mingwX64("globalState")
|
||||
else -> throw GradleException("Host OS '$hostOs' is not supported in Kotlin/Native $project.")
|
||||
}
|
||||
|
||||
hostTarget.apply {
|
||||
binaries {
|
||||
executable {
|
||||
entryPoint = "sample.globalstate.main"
|
||||
}
|
||||
}
|
||||
compilations["main"].cinterops {
|
||||
val global by creating
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
kotlin.code.style=official
|
||||
kotlin.import.noCommonSourceSets=true
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package sample.globalstate
|
||||
|
||||
import kotlin.native.concurrent.*
|
||||
import kotlinx.cinterop.*
|
||||
import platform.posix.*
|
||||
|
||||
inline fun Int.ensureUnixCallResult(op: String, predicate: (Int) -> Boolean = { x -> x == 0} ): Int {
|
||||
if (!predicate(this)) {
|
||||
throw Error("$op: ${strerror(posix_errno())!!.toKString()}")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
data class SharedDataMember(val double: Double)
|
||||
|
||||
data class SharedData(val string: String, val int: Int, val member: SharedDataMember)
|
||||
|
||||
// Here we access the same shared frozen Kotlin object from multiple threads.
|
||||
val globalObject: SharedData?
|
||||
get() = sharedData.frozenKotlinObject?.asStableRef<SharedData>()?.get()
|
||||
|
||||
fun dumpShared(prefix: String) {
|
||||
println("""
|
||||
$prefix: ${pthread_self()} x=${sharedData.x} f=${sharedData.f} s=${sharedData.string!!.toKString()}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun main() {
|
||||
// Arena owning all native allocs.
|
||||
val arena = Arena()
|
||||
|
||||
// Assign global data.
|
||||
sharedData.x = 239
|
||||
sharedData.f = 0.5f
|
||||
sharedData.string = "Hello Kotlin!".cstr.getPointer(arena)
|
||||
|
||||
// Here we create detached mutable object, which could be later reattached by another thread.
|
||||
sharedData.kotlinObject = DetachedObjectGraph {
|
||||
SharedData("A string", 42, SharedDataMember(2.39))
|
||||
}.asCPointer()
|
||||
|
||||
// Here we create shared frozen object reference,
|
||||
val stableRef = StableRef.create(SharedData("Shared", 239, SharedDataMember(2.71)).freeze())
|
||||
sharedData.frozenKotlinObject = stableRef.asCPointer()
|
||||
dumpShared("thread1")
|
||||
println("frozen is $globalObject")
|
||||
|
||||
// Start a new thread, that sees the variable.
|
||||
// memScoped is needed to pass thread's local address to pthread_create().
|
||||
memScoped {
|
||||
val thread = alloc<pthread_tVar>()
|
||||
pthread_create(thread.ptr, null, staticCFunction { argC ->
|
||||
initRuntimeIfNeeded()
|
||||
dumpShared("thread2")
|
||||
val kotlinObject = DetachedObjectGraph<SharedData>(sharedData.kotlinObject).attach()
|
||||
val arg = DetachedObjectGraph<SharedDataMember>(argC).attach()
|
||||
println("thread arg is $arg Kotlin object is $kotlinObject frozen is $globalObject")
|
||||
// Workaround for compiler issue.
|
||||
null as COpaquePointer?
|
||||
}, DetachedObjectGraph { SharedDataMember(3.14)}.asCPointer() ).ensureUnixCallResult("pthread_create")
|
||||
pthread_join(thread.value, null).ensureUnixCallResult("pthread_join")
|
||||
}
|
||||
|
||||
// At this moment we do not need data stored in shared data, so clean up the data
|
||||
// and free memory.
|
||||
sharedData.string = null
|
||||
stableRef.dispose()
|
||||
arena.clear()
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package = sample.globalstate
|
||||
|
||||
---
|
||||
typedef struct {
|
||||
int x;
|
||||
float f;
|
||||
char* string;
|
||||
void* kotlinObject;
|
||||
void* frozenKotlinObject;
|
||||
} SharedDataStruct;
|
||||
|
||||
SharedDataStruct sharedData;
|
||||
Reference in New Issue
Block a user