more KMP targets
This commit is contained in:
parent
3c33eb3bd9
commit
e9082af4de
@ -17,6 +17,7 @@ repositories {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(17)
|
||||
jvm {
|
||||
compilations.all {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
@ -48,15 +49,32 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
val hostOs = System.getProperty("os.name")
|
||||
val isMingwX64 = hostOs.startsWith("Windows")
|
||||
val nativeTarget = when {
|
||||
hostOs == "Mac OS X" -> macosX64("native")
|
||||
hostOs == "Linux" -> linuxX64("native")
|
||||
isMingwX64 -> mingwX64("native")
|
||||
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
|
||||
// val hostOs = System.getProperty("os.name")
|
||||
// val isMingwX64 = hostOs.startsWith("Windows")
|
||||
// val nativeTarget = when {
|
||||
// hostOs == "Mac OS X" -> macosX64("native")
|
||||
// hostOs == "Linux" -> linuxX64("native")
|
||||
// isMingwX64 -> mingwX64("native")
|
||||
// else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
|
||||
// }
|
||||
|
||||
linuxX64("native") {
|
||||
binaries.staticLib {
|
||||
baseName = "mp_bintools"
|
||||
}
|
||||
}
|
||||
|
||||
wasmJs {
|
||||
browser()
|
||||
binaries.executable()
|
||||
}
|
||||
|
||||
|
||||
mingwX64() {
|
||||
binaries.staticLib {
|
||||
baseName = "mp_bintools"
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
all {
|
||||
@ -66,29 +84,35 @@ kotlin {
|
||||
}
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")
|
||||
// this is actually a bug: we need only the core, but bare core causes strange errors
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
|
||||
// api("net.sergeych:mp_stools:[1.3.3,)")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.5.0")
|
||||
}
|
||||
}
|
||||
val commonTest by getting {
|
||||
dependencies {
|
||||
implementation(kotlin("test"))
|
||||
implementation("net.sergeych:mp_stools:1.4.1")
|
||||
implementation("net.sergeych:mp_stools:1.4.4-SNAPSHOT")
|
||||
}
|
||||
}
|
||||
val jvmMain by getting
|
||||
val jvmTest by getting
|
||||
val jsMain by getting {
|
||||
dependencies {
|
||||
implementation("net.sergeych:mp_stools:1.4.3")
|
||||
implementation("net.sergeych:mp_stools:1.4.4-SNAPSHOT")
|
||||
}
|
||||
}
|
||||
val jsTest by getting
|
||||
val nativeMain by getting
|
||||
val nativeTest by getting
|
||||
val wasmJsMain by getting {
|
||||
dependencies {
|
||||
implementation("net.sergeych:mp_stools:1.4.4-SNAPSHOT")
|
||||
}
|
||||
}
|
||||
val wasmJsTest by getting
|
||||
}
|
||||
|
||||
publishing {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.sergeych.synctools
|
||||
|
||||
import net.sergeych.tools.AtomicCounter
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
@ -0,0 +1,25 @@
|
||||
package net.sergeych.bintools
|
||||
|
||||
/**
|
||||
* Create per-platform default named storage.
|
||||
*
|
||||
* - In the browser, it uses the `Window.localStorage` prefixing items
|
||||
* by a string containing the [name]
|
||||
*
|
||||
* - In the JVM environment it uses folder-based storage on the file system. The name
|
||||
* is considered to be a folder name (the whole path which will be automatically created)
|
||||
* using the following rules:
|
||||
* - when the name starts with slash (`/`) it is treated as an absolute path to a folder
|
||||
* - when the name contains slash, it is considered to be a relative folder to the
|
||||
* `User.home` directory, like "`~/`" on unix systems.
|
||||
* - otherwise, the folder will be created in "`~/.local_storage`" parent directory
|
||||
* (which also will be created if needed).
|
||||
*
|
||||
* - For the native platorms it is not yet implemented (but will be soon).
|
||||
*
|
||||
* See [DataKVStorage] and [DataProvider] to implement a KVStorage on filesystems and like,
|
||||
* and `FileDataProvider` class on JVM target.
|
||||
*/
|
||||
actual fun defaultNamedStorage(name: String): KVStorage {
|
||||
TODO("Not yet implemented")
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package net.sergeych.synctools
|
||||
|
||||
import kotlinx.atomicfu.locks.ReentrantLock
|
||||
|
||||
/**
|
||||
* Native implementation uses `ReentrantLock`]
|
||||
*/
|
||||
actual fun ProtectedOp(): ProtectedOpImplementation = object : ProtectedOpImplementation {
|
||||
private val access = ReentrantLock()
|
||||
override fun lock() {
|
||||
access.lock()
|
||||
}
|
||||
|
||||
override fun unlock() {
|
||||
access.unlock()
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package net.sergeych.synctools
|
||||
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withTimeout
|
||||
|
||||
@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
|
||||
actual class WaitHandle {
|
||||
private val channel = Channel<Unit>()
|
||||
actual fun await(milliseconds: Long): Boolean {
|
||||
return runBlocking {
|
||||
try {
|
||||
if( milliseconds > 0) {
|
||||
withTimeout(milliseconds) {
|
||||
channel.receive()
|
||||
true
|
||||
}
|
||||
}
|
||||
else {
|
||||
channel.receive()
|
||||
true
|
||||
}
|
||||
}
|
||||
catch(_: TimeoutCancellationException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actual fun wakeUp() {
|
||||
runBlocking { channel.send(Unit) }
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package net.sergeych.bintools
|
||||
|
||||
import kotlinx.browser.localStorage
|
||||
import net.sergeych.mp_tools.decodeBase64Compact
|
||||
import net.sergeych.mp_tools.encodeToBase64Compact
|
||||
import org.w3c.dom.Storage
|
||||
import org.w3c.dom.set
|
||||
|
||||
|
||||
/**
|
||||
* Create per-platform default named storage.
|
||||
*
|
||||
* - In the browser, it uses the `Window.localStorage` prefixing items
|
||||
* by a string containing the [name]
|
||||
*
|
||||
* - In the JVM environment it uses folder-based storage on the file system. The name
|
||||
* is considered to be a folder name (the whole path which will be automatically created)
|
||||
* using the following rules:
|
||||
* - when the name starts with slash (`/`) it is treated as an absolute path to a folder
|
||||
* - when the name contains slash, it is considered to be a relative folder to the
|
||||
* `User.home` directory, like "`~/`" on unix systems.
|
||||
* - otherwise, the folder will be created in "`~/.local_storage`" parent directory
|
||||
* (which also will be created if needed).
|
||||
*
|
||||
* - For the native platorms it is not yet implemented (but will be soon).
|
||||
*
|
||||
* See [DataKVStorage] and [DataProvider] to implement a KVStorage on filesystems and like,
|
||||
* and `FileDataProvider` class on JVM target.
|
||||
*/
|
||||
actual fun defaultNamedStorage(name: String): KVStorage = BrowserKVStorage(name, localStorage)
|
||||
|
||||
/**
|
||||
* Default KV storage in browser. Use if with `localStorage` or `sessionStorage`. It uses
|
||||
* prefix for storage values not to collide with other data, beware of it.
|
||||
*/
|
||||
class BrowserKVStorage(keyPrefix: String, private val bst: Storage) : KVStorage {
|
||||
|
||||
private val prefix = "$keyPrefix:"
|
||||
fun k(key: String) = "$prefix$key"
|
||||
override fun get(key: String): ByteArray? {
|
||||
return bst.getItem(k(key))?.decodeBase64Compact()
|
||||
}
|
||||
|
||||
override fun set(key: String, value: ByteArray?) {
|
||||
val corrected = k(key)
|
||||
if (value == null)
|
||||
bst.removeItem(corrected)
|
||||
else
|
||||
bst.set(corrected, value.encodeToBase64Compact())
|
||||
}
|
||||
|
||||
override val keys: Set<String>
|
||||
get() {
|
||||
val kk = mutableListOf<String>()
|
||||
for (i in 0 until bst.length) {
|
||||
val k = bst.key(i) ?: break
|
||||
if( k.startsWith(prefix)) {
|
||||
kk += k.substring(prefix.length)
|
||||
}
|
||||
}
|
||||
return kk.toSet()
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package net.sergeych.synctools
|
||||
|
||||
import kotlinx.atomicfu.locks.ReentrantLock
|
||||
|
||||
/**
|
||||
* Get the platform-depended implementation of a mutex. It does nothing in the
|
||||
* browser and use appropriate mechanics on JVM and native targets. See
|
||||
* [ProtectedOpImplementation.invoke], [ProtectedOpImplementation.withLock]
|
||||
* ```kotlin
|
||||
* val op = ProtectedOp()
|
||||
* //...
|
||||
* op {
|
||||
* // mutually exclusive execution
|
||||
* println("sequential execution here")
|
||||
* }
|
||||
* ~~~
|
||||
*/
|
||||
actual fun ProtectedOp(): ProtectedOpImplementation = object: ProtectedOpImplementation {
|
||||
val rlock = ReentrantLock()
|
||||
override fun lock() {
|
||||
rlock.lock()
|
||||
}
|
||||
|
||||
override fun unlock() {
|
||||
rlock.unlock()
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package net.sergeych.synctools
|
||||
|
||||
/**
|
||||
* Platform-independent interface to thread wait/notify. Does nothing in JS/browser,
|
||||
* and uses appropriate mechanics on other platforms.
|
||||
*
|
||||
* Wasm is effictively songle threaded at the moment
|
||||
*/
|
||||
@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
|
||||
actual class WaitHandle {
|
||||
actual fun await(milliseconds: Long): Boolean {
|
||||
// in JS we can't wait: no threads
|
||||
return true
|
||||
}
|
||||
|
||||
actual fun wakeUp() {
|
||||
// in JS we can't wait: no threads
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user