All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nativeLinuxLikeMain.app.cash.sqldelight.driver.native.util.PoolLock.kt Maven / Gradle / Ivy

package app.cash.sqldelight.driver.native.util

import co.touchlab.stately.concurrency.AtomicBoolean
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.alloc
import kotlinx.cinterop.free
import kotlinx.cinterop.nativeHeap
import kotlinx.cinterop.ptr
import platform.posix.pthread_cond_destroy
import platform.posix.pthread_cond_init
import platform.posix.pthread_cond_signal
import platform.posix.pthread_cond_t
import platform.posix.pthread_cond_wait
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 platform.posix.pthread_mutexattr_destroy
import platform.posix.pthread_mutexattr_init
import platform.posix.pthread_mutexattr_settype
import platform.posix.pthread_mutexattr_t

@OptIn(ExperimentalForeignApi::class)
internal actual class PoolLock actual constructor(reentrant: Boolean) {
  private val isActive = AtomicBoolean(true)
  private val attr = nativeHeap.alloc()
    .apply {
      pthread_mutexattr_init(ptr)
      if (reentrant) {
        pthread_mutexattr_settype(ptr, pthread_mutex_recursive)
      }
    }
  private val mutex = nativeHeap.alloc()
    .apply { pthread_mutex_init(ptr, attr.ptr) }
  private val cond = nativeHeap.alloc()
    .apply { pthread_cond_init(ptr, null) }

  actual fun  withLock(
    action: CriticalSection.() -> R,
  ): R {
    check(isActive.value)
    pthread_mutex_lock(mutex.ptr)

    val result: R

    try {
      result = action(CriticalSection())
    } finally {
      pthread_mutex_unlock(mutex.ptr)
    }

    return result
  }

  actual fun notifyConditionChanged() {
    pthread_cond_signal(cond.ptr)
  }

  actual fun close(): Boolean {
    if (isActive.compareAndSet(expected = true, new = false)) {
      pthread_cond_destroy(cond.ptr)
      pthread_mutex_destroy(mutex.ptr)
      pthread_mutexattr_destroy(attr.ptr)
      nativeHeap.free(cond)
      nativeHeap.free(mutex)
      nativeHeap.free(attr)
      return true
    }

    return false
  }

  actual inner class CriticalSection {
    actual fun  loopForConditionalResult(block: () -> R?): R {
      check(isActive.value)

      var result = block()

      while (result == null) {
        pthread_cond_wait(cond.ptr, mutex.ptr)
        result = block()
      }

      return result
    }
  }
}

// https://youtrack.jetbrains.com/issue/KT-48997
internal expect val pthread_mutex_recursive: Int




© 2015 - 2025 Weber Informatics LLC | Privacy Policy