diff --git a/.gitignore b/.gitignore index 116ea92..405f242 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -/.idea/ +.idea/ gradle/ .gradle/ build/ diff --git a/build.gradle.kts b/build.gradle.kts index 81e7806..f131717 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,6 +22,7 @@ version = "0.1" repositories { mavenCentral() + maven("https://maven.landgrafhomyak.ru/") } kotlin { @@ -68,7 +69,13 @@ kotlin { compileOnly("org.jetbrains.kotlin:kotlin-annotations-jvm:${this@kotlin.coreLibrariesVersion}") } } - + mingwX64().compilations["main"].defaultSourceSet { + dependencies { + implementation("ru.landgrafhomyak.utility:highlevel-try-finally:0.6") + implementation("ru.landgrafhomyak.utility:closeable-state-1:1.2") + implementation("ru.landgrafhomyak.utility:kotlin-native-interop-utilities-0:0.1") + } + } val notJvmMain by creating { dependsOn(commonMain) } val notJvmTest by creating { dependsOn(commonTest) } @@ -96,11 +103,13 @@ kotlin { this@target.compilations.getByName("main").defaultSourceSet.dependsOn(multithreadPlatformMain) this@target.compilations.getByName("test").defaultSourceSet.dependsOn(multithreadPlatformTest) } - } + + val windowsMain by creating { dependsOn(multithreadPlatformMain) } + val windowsTest by creating { dependsOn(multithreadPlatformTest) } + mingwX64().compilations["main"].defaultSourceSet.dependsOn(windowsMain) + mingwX64().compilations["test"].defaultSourceSet.dependsOn(windowsTest) } - - } publishing { diff --git a/src/windowsMain/kotlin/ru/landgrafhomyak/multitasking_0/threads/ThreadLocalVariable.kt b/src/windowsMain/kotlin/ru/landgrafhomyak/multitasking_0/threads/ThreadLocalVariable.kt new file mode 100644 index 0000000..02e63fd --- /dev/null +++ b/src/windowsMain/kotlin/ru/landgrafhomyak/multitasking_0/threads/ThreadLocalVariable.kt @@ -0,0 +1,67 @@ +package ru.landgrafhomyak.multitasking_0.threads + +import kotlin.concurrent.atomics.ExperimentalAtomicApi +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.cinterop.StableRef +import platform.windows.DWORD +import platform.windows.ERROR_SUCCESS +import platform.windows.GetLastError +import platform.windows.LPVOID +import platform.windows.TLS_OUT_OF_INDEXES +import platform.windows.TlsAlloc +import platform.windows.TlsFree +import platform.windows.TlsGetValue +import platform.windows.TlsSetValue +import ru.landgrafhomyak.utility.closeable_state_1.CloseableState +import ru.landgrafhomyak.utility.closeable_state_1.ManualStateManipulation +import ru.landgrafhomyak.utility.closeable_state_1.OwnedUsagesCounter +import ru.landgrafhomyak.utility.closeable_state_1.withUse +import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2 +import ru.landgrafhomyak.utility.kotlin_native_interop_stdlib_0.windows.WindowsApiException +import ru.landgrafhomyak.utility.kotlin_native_interop_stdlib_0.windows.zeroToWinApiErr + +@Suppress("JoinDeclarationAndAssignment") +@OptIn(ExperimentalForeignApi::class, ExperimentalAtomicApi::class) +internal class ThreadLocalVariable { + private val _windows_tls_index: DWORD + private val _garbageCollectionDisabler: StableRef + private val _state: CloseableState.AllowsConcurrency + + init { + this._state = OwnedUsagesCounter(this) + this._garbageCollectionDisabler = StableRef.create(this) + safeAutoClose2( + action = { + this._windows_tls_index = TlsAlloc() + if (this._windows_tls_index == TLS_OUT_OF_INDEXES) + WindowsApiException.throwFromLastWindowsErr() + }, + onError = { this._garbageCollectionDisabler.dispose() } + ) + } + + + fun dealloc() { + @OptIn(ManualStateManipulation::class) + this._state.close() + + zeroToWinApiErr { TlsFree(this._windows_tls_index) } + this._garbageCollectionDisabler.dispose() + } + + fun get(): LPVOID? { + this._state.withUse { + val value = TlsGetValue(this._windows_tls_index) + val errCode = GetLastError() + if (errCode != ERROR_SUCCESS.toUInt()) + WindowsApiException.throwFromWindowsErrCode(errCode) + return value + } + } + + fun set(value: LPVOID?) { + this._state.withUse { + zeroToWinApiErr { TlsSetValue(this._windows_tls_index, value) } + } + } +} \ No newline at end of file