[Gradle] Share NativeDistributionCommonizerLock with 'cleanNativeDistributionCommonization' task

KT-52172
This commit is contained in:
Sebastian Sellmair
2022-12-09 12:25:01 +01:00
committed by Space Team
parent 6e0f5e8212
commit d12fbcf574
3 changed files with 73 additions and 55 deletions
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.gradle.targets.native.internal
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.compilerRunner.maybeCreateCommonizerClasspathConfiguration
import org.jetbrains.kotlin.gradle.internal.isInIdeaSync
@@ -140,7 +140,7 @@ internal val Project.commonizeNativeDistributionTask: TaskProvider<NativeDistrib
)
}
internal val Project.cleanNativeDistributionCommonizerTask: TaskProvider<Delete>?
internal val Project.cleanNativeDistributionCommonizerTask: TaskProvider<DefaultTask>?
get() {
val commonizeNativeDistributionTask = commonizeNativeDistributionTask ?: return null
return rootProject.locateOrRegisterTask(
@@ -148,7 +148,15 @@ internal val Project.cleanNativeDistributionCommonizerTask: TaskProvider<Delete>
configureTask = {
group = "interop"
description = "Deletes all previously commonized klib's from the Kotlin/Native distribution"
delete(commonizeNativeDistributionTask.map { it.rootOutputDirectory })
val commonizerDirectory = commonizeNativeDistributionTask.map { it.rootOutputDirectory }
outputs.dir(commonizerDirectory)
doFirst {
NativeDistributionCommonizerLock(commonizerDirectory.get()).withLock {
delete(commonizerDirectory.get())
}
}
}
)
}
@@ -11,12 +11,8 @@ import org.gradle.api.logging.Logger
import org.jetbrains.kotlin.commonizer.*
import org.jetbrains.kotlin.commonizer.CommonizerOutputFileLayout.resolveCommonizedDirectory
import java.io.File
import java.io.FileOutputStream
import java.io.ObjectInputStream
import java.io.Serializable
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
class NativeDistributionCommonizerCache(
private val outputDirectory: File,
@@ -100,59 +96,13 @@ class NativeDistributionCommonizerCache(
* even between multiple process (Gradle Daemons)
*/
@Transient
private var lock = Lock()
private var lock = NativeDistributionCommonizerLock(outputDirectory, ::logInfo)
private fun logInfo(message: String) =
logger.info("Native Distribution Commonization: $message")
private inner class Lock {
private val lockedOutputDirectories = mutableSetOf<File>()
fun <T> withLock(action: () -> T): T {
/* Enter intra-process wide lock */
intraProcessLock.withLock {
if (outputDirectory in lockedOutputDirectories) {
/* Already acquired this directory and re-entered: We can just execute the action */
return action()
}
/* Lock output directory inter-process wide */
outputDirectory.mkdirs()
val lockfile = outputDirectory.resolve(".lock")
logInfo("Acquire lock: ${lockfile.path} ...")
FileOutputStream(outputDirectory.resolve(".lock")).use { stream ->
val lock = stream.channel.lock()
assert(lock.isValid)
return try {
logInfo("Lock acquired: ${lockfile.path}")
lockedOutputDirectories.add(outputDirectory)
action()
} finally {
lockedOutputDirectories.remove(outputDirectory)
lock.release()
logInfo("Lock released: ${lockfile.path}")
}
}
}
}
fun checkLocked(outputDirectory: File) {
check(intraProcessLock.isHeldByCurrentThread) {
"Expected lock to be held by current thread ${Thread.currentThread().name}"
}
check(outputDirectory in lockedOutputDirectories) {
"Expected $outputDirectory to be locked. Locked directories: $lockedOutputDirectories"
}
}
}
private fun readObject(input: ObjectInputStream) {
input.defaultReadObject()
lock = Lock()
}
private companion object {
val intraProcessLock: ReentrantLock = ReentrantLock()
lock = NativeDistributionCommonizerLock(outputDirectory, ::logInfo)
}
}
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.targets.native.internal
import java.io.File
import java.io.FileOutputStream
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock
internal class NativeDistributionCommonizerLock(
private val outputDirectory: File,
private val logInfo: (message: String) -> Unit = {}
) {
private companion object {
val intraProcessLock: ReentrantLock = ReentrantLock()
}
private val lockedOutputDirectories = mutableSetOf<File>()
fun <T> withLock(action: () -> T): T {
/* Enter intra-process wide lock */
intraProcessLock.withLock {
if (outputDirectory in lockedOutputDirectories) {
/* Already acquired this directory and re-entered: We can just execute the action */
return action()
}
/* Lock output directory inter-process wide */
outputDirectory.mkdirs()
val lockfile = outputDirectory.resolve(".lock")
logInfo("Acquire lock: ${lockfile.path} ...")
FileOutputStream(outputDirectory.resolve(".lock")).use { stream ->
val lock = stream.channel.lock()
assert(lock.isValid)
return try {
logInfo("Lock acquired: ${lockfile.path}")
lockedOutputDirectories.add(outputDirectory)
action()
} finally {
lockedOutputDirectories.remove(outputDirectory)
lock.release()
logInfo("Lock released: ${lockfile.path}")
}
}
}
}
fun checkLocked(outputDirectory: File) {
check(intraProcessLock.isHeldByCurrentThread) {
"Expected lock to be held by current thread ${Thread.currentThread().name}"
}
check(outputDirectory in lockedOutputDirectories) {
"Expected $outputDirectory to be locked. Locked directories: $lockedOutputDirectories"
}
}
}