Mutex implementation for linux

This commit is contained in:
Andrew Golovashevich 2025-03-17 16:08:06 +03:00
commit 5d17c5f7cf
9 changed files with 195 additions and 0 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/.idea/
gradle/
.gradle/
build/
*.class
*.jar
/out/
/gradlew*
.kotlin/

21
build.gradle.kts Normal file
View File

@ -0,0 +1,21 @@
plugins {
kotlin("multiplatform") version "2.1.0"
}
repositories {
mavenCentral()
}
kotlin {
jvm()
mingwX64()
sourceSets {
commonMain {
dependencies {
implementation("io.ktor:ktor-client-core:3.1.1")
implementation("io.ktor:ktor-network:3.1.1")
}
}
}
}

View File

@ -0,0 +1,21 @@
plugins {
kotlin("multiplatform") version "2.1.0"
}
repositories {
mavenCentral()
}
kotlin {
mingwX64()
linuxX64()
macosX64()
macosArm64()
sourceSets {
commonMain {
dependencies {
}
}
}
}

View File

@ -0,0 +1,16 @@
package ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.CVariable
import kotlinx.cinterop.ExperimentalForeignApi
import platform.posix.malloc
import kotlinx.cinterop.sizeOf as sizeOf_signed
@OptIn(ExperimentalForeignApi::class)
object CUtilities {
inline fun <reified T : CVariable> sizeOf(): ULong = sizeOf_signed<T>().toULong()
@Suppress("UNCHECKED_CAST")
inline fun <reified T : CVariable> newOrOom() = (malloc(sizeOf<T>()) ?: throw OutOfMemoryError()) as CPointer<T>
}

View File

@ -0,0 +1,45 @@
package ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.toKStringFromUtf8
import platform.posix.errno
import platform.posix.strerror
object LinuxUtilities {
@OptIn(ExperimentalForeignApi::class, ExperimentalContracts::class)
inline fun throwErrno(
createError: (errnoDescription: String) -> Throwable,
): Nothing {
contract {
callsInPlace(createError, InvocationKind.AT_MOST_ONCE)
}
val origErrno = errno
throwErrno(origErrno, createError)
}
@OptIn(ExperimentalForeignApi::class, ExperimentalContracts::class)
inline fun throwErrno(
origErrno: Int,
createError: (errnoDescription: String) -> Throwable,
): Nothing {
contract {
callsInPlace(createError, InvocationKind.AT_MOST_ONCE)
}
val raw = strerror(origErrno)
if (raw != null) {
throw createError(raw.toKStringFromUtf8())
} else {
val strerrErrno = errno
try {
throw createError("Unknown error (errno=${origErrno})")
} catch (t: Throwable) {
t.addSuppressed(RuntimeException("Failed to get errno description (failed with errno=${strerrErrno})"))
throw t
}
}
}
}

View File

@ -0,0 +1,22 @@
plugins {
kotlin("multiplatform") version "2.1.0"
}
repositories {
mavenCentral()
}
kotlin {
mingwX64()
linuxX64()
macosX64()
macosArm64()
sourceSets {
nativeMain {
dependencies {
implementation(project(":modules:low-level:c-interop-utilities"))
}
}
}
}

View File

@ -0,0 +1,8 @@
package ru.landgrafhomyak.bgtu.networks0.low_level.multithreading
expect class TMutex : AutoCloseable {
constructor()
fun lock()
fun unlock()
}

View File

@ -0,0 +1,50 @@
package ru.landgrafhomyak.bgtu.networks0.low_level.multithreading
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.ExperimentalForeignApi
import platform.posix.free
import platform.posix.pthread_mutex_destroy
import platform.posix.pthread_mutex_init
import platform.posix.pthread_mutex_lock
import platform.posix.pthread_mutex_t
import platform.posix.pthread_mutex_unlock
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.CUtilities
import ru.landgrafhomyak.bgtu.networks0.low_level.c_interop_utilities.LinuxUtilities
@Suppress("JoinDeclarationAndAssignment", "CanBeVal", "ConvertSecondaryConstructorToPrimary")
@OptIn(ExperimentalForeignApi::class)
actual class TMutex : AutoCloseable {
private var isClosed: Boolean
private val descriptor: CPointer<pthread_mutex_t>
actual constructor() {
this.descriptor = CUtilities.newOrOom<pthread_mutex_t>()
var err = pthread_mutex_init(this.descriptor, null)
if (err != 0)
LinuxUtilities.throwErrno(err) { d -> RuntimeException("Failed to create pthreads mutex: $d") }
this.isClosed = false
}
actual fun lock() {
if (this.isClosed) throw IllegalStateException("Mutex was destroyed")
var err = pthread_mutex_lock(this.descriptor)
if (err != 0)
LinuxUtilities.throwErrno(err) { d -> RuntimeException("Failed to lock pthreads mutex: $d") }
}
actual fun unlock() {
if (this.isClosed) throw IllegalStateException("Mutex was destroyed")
var err = pthread_mutex_unlock(this.descriptor)
if (err != 0)
LinuxUtilities.throwErrno(err) { d -> RuntimeException("Failed to unlock pthreads mutex: $d") }
}
override fun close() {
if (this.isClosed) return
this.isClosed = true
var err = pthread_mutex_destroy(this.descriptor)
if (err != 0)
LinuxUtilities.throwErrno(err) { d -> RuntimeException("Failed to destroy pthreads mutex: $d") }
free(this.descriptor)
}
}

3
settings.gradle.kts Normal file
View File

@ -0,0 +1,3 @@
include(":modules:low-level:c-interop-utilities")
include(":modules:low-level:multithreading")
include(":modules:low-level:sockets")