2023-05-18 04:36:15 -07:00
|
|
|
package cash.z.ecc.android.sdk.internal.jni
|
2021-10-21 13:05:02 -07:00
|
|
|
|
|
|
|
import kotlinx.coroutines.Dispatchers
|
|
|
|
import kotlinx.coroutines.sync.Mutex
|
|
|
|
import kotlinx.coroutines.sync.withLock
|
|
|
|
import kotlinx.coroutines.withContext
|
|
|
|
import java.util.concurrent.atomic.AtomicBoolean
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads a native library once. This class is thread-safe.
|
|
|
|
*
|
|
|
|
* To use this class, create a singleton instance for each given [libraryName].
|
|
|
|
*
|
|
|
|
* @param libraryName Name of the library to load.
|
|
|
|
*/
|
|
|
|
internal class NativeLibraryLoader(private val libraryName: String) {
|
|
|
|
private val isLoaded = AtomicBoolean(false)
|
|
|
|
private val mutex = Mutex()
|
|
|
|
|
2022-12-12 21:02:25 -08:00
|
|
|
/**
|
|
|
|
* @param onLoad Callback allowing additional initialization after the native library is loaded. This will only be
|
|
|
|
* invoked the first time this method is called for the lifetime of the process.
|
|
|
|
*/
|
|
|
|
suspend fun load(onLoad: suspend () -> Unit) {
|
2021-10-21 13:05:02 -07:00
|
|
|
// Double-checked locking to avoid the Mutex unless necessary, as the hot path is
|
|
|
|
// for the library to be loaded since this should only run once for the lifetime
|
|
|
|
// of the application
|
|
|
|
if (!isLoaded.get()) {
|
|
|
|
mutex.withLock {
|
|
|
|
if (!isLoaded.get()) {
|
2022-12-12 21:02:25 -08:00
|
|
|
loadNativeLibrary()
|
|
|
|
onLoad()
|
2021-10-21 13:05:02 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-12 21:02:25 -08:00
|
|
|
private suspend fun loadNativeLibrary() {
|
2022-11-29 05:08:24 -08:00
|
|
|
runCatching {
|
2023-05-18 04:36:15 -07:00
|
|
|
loadLibrarySuspend(libraryName)
|
2021-10-21 13:05:02 -07:00
|
|
|
isLoaded.set(true)
|
2022-11-29 05:08:24 -08:00
|
|
|
}.onFailure {
|
|
|
|
// Fail fast, because this is not a recoverable error
|
|
|
|
throw AssertionError("Failed loading native library $libraryName", it)
|
2021-10-21 13:05:02 -07:00
|
|
|
}
|
|
|
|
}
|
2021-11-18 04:10:30 -08:00
|
|
|
}
|
2022-11-29 05:08:24 -08:00
|
|
|
|
2024-01-04 12:21:32 -08:00
|
|
|
private suspend fun loadLibrarySuspend(libraryName: String) =
|
|
|
|
withContext(Dispatchers.IO) {
|
|
|
|
System.loadLibrary(libraryName)
|
|
|
|
}
|