From 0f85696ffb2fcf9625f0c0328968cb4b67301623 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Tue, 16 Jan 2018 18:31:50 +0300 Subject: [PATCH] Global state demo. (#1236) --- samples/globalState/README.md | 9 +++ samples/globalState/build.gradle | 15 +++++ .../globalState/src/main/c_interop/global.def | 10 ++++ samples/globalState/src/main/kotlin/Global.kt | 59 +++++++++++++++++++ samples/settings.gradle | 1 + 5 files changed, 94 insertions(+) create mode 100644 samples/globalState/README.md create mode 100644 samples/globalState/build.gradle create mode 100644 samples/globalState/src/main/c_interop/global.def create mode 100644 samples/globalState/src/main/kotlin/Global.kt diff --git a/samples/globalState/README.md b/samples/globalState/README.md new file mode 100644 index 00000000000..54c8eb5ca2f --- /dev/null +++ b/samples/globalState/README.md @@ -0,0 +1,9 @@ +# Shared global state + + This example shows how one could implement global shared state using interop mechanisms. + +To build use `../gradlew build`. + +To run use `./build/konan/bin//Globals.exe`. + + diff --git a/samples/globalState/build.gradle b/samples/globalState/build.gradle new file mode 100644 index 00000000000..094c8c62b9a --- /dev/null +++ b/samples/globalState/build.gradle @@ -0,0 +1,15 @@ +apply plugin: 'konan' + +konan.targets = ['macbook', 'linux', 'mingw'] + +konanArtifacts { + interop('global') { + defFile 'src/main/c_interop/global.def' + } + + program('Globals') { + libraries { + artifact 'global' + } + } +} diff --git a/samples/globalState/src/main/c_interop/global.def b/samples/globalState/src/main/c_interop/global.def new file mode 100644 index 00000000000..0496c1ed69d --- /dev/null +++ b/samples/globalState/src/main/c_interop/global.def @@ -0,0 +1,10 @@ +package = global + +--- +typedef struct { + int x; + float f; + char* string; +} SharedData; + +SharedData sharedData; diff --git a/samples/globalState/src/main/kotlin/Global.kt b/samples/globalState/src/main/kotlin/Global.kt new file mode 100644 index 00000000000..bd2e4547266 --- /dev/null +++ b/samples/globalState/src/main/kotlin/Global.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import global.* +import kotlinx.cinterop.* +import platform.posix.* + +fun Int.ensureUnixCallResult(op: String, predicate: (Int) -> Boolean = { x -> x >= 0} ): Int { + if (!predicate(this)) { + throw Error("$op: ${strerror(posix_errno())!!.toKString()}") + } + return this +} + +fun dumpShared(prefix: String) = + println("$prefix: ${pthread_self().rawValue} x=${sharedData.x} f=${sharedData.f} s=${sharedData.string!!.toKString()}") + +fun main(args: Array) { + // 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) + dumpShared("thread1") + + // 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_create(thread.ptr, null, staticCFunction { + _ -> + initRuntimeIfNeeded() + dumpShared("thread2") + // Workaround for compiler issue. + null as COpaquePointer? + }, null).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 + arena.clear() +} diff --git a/samples/settings.gradle b/samples/settings.gradle index cdb2f7b5ef6..77562f9a5b9 100644 --- a/samples/settings.gradle +++ b/samples/settings.gradle @@ -3,6 +3,7 @@ include ':calculator' include ':csvparser' include ':gitchurn' +include ':globalState' include ':gtk' include ':libcurl' include ':nonBlockingEchoServer'