Skip to content

Commit 1588d55

Browse files
committed
Move to pthread_getspecific
1 parent 22f8b3a commit 1588d55

File tree

3 files changed

+30
-26
lines changed

3 files changed

+30
-26
lines changed

Sources/JNICore.swift

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@ public func JNI_OnLoad( jvm: UnsafeMutablePointer<JavaVM?>, ptr: UnsafeRawPointe
1919
JNI.jvm = jvm
2020
let env: UnsafeMutablePointer<JNIEnv?>? = JNI.GetEnv()
2121
JNI.api = env!.pointee!.pointee
22-
JNI.envCache[JNI.threadKey] = env
23-
#if os(Android)
24-
DispatchQueue.setThreadDetachCallback( JNI_DetachCurrentThread )
25-
#endif
22+
if pthread_setspecific( JNICore.envVarKey, env ) != 0 {
23+
JNI.report( "Could not set pthread specific GetEnv()" )
24+
}
2625

2726
// Save ContextClassLoader for FindClass usage
2827
// When a thread is attached to the VM, the context class loader is the bootstrap loader.
@@ -35,9 +34,6 @@ public func JNI_OnLoad( jvm: UnsafeMutablePointer<JavaVM?>, ptr: UnsafeRawPointe
3534

3635
public func JNI_DetachCurrentThread() {
3736
_ = JNI.jvm?.pointee?.pointee.DetachCurrentThread( JNI.jvm )
38-
JNI.envLock.lock()
39-
JNI.envCache[JNI.threadKey] = nil
40-
JNI.envLock.unlock()
4137
}
4238

4339
public let JNI = JNICore()
@@ -48,21 +44,25 @@ open class JNICore {
4844
open var api: JNINativeInterface_!
4945
open var classLoader: jobject?
5046

51-
open var envCache = [pthread_t:UnsafeMutablePointer<JNIEnv?>?]()
52-
fileprivate let envLock = NSLock()
53-
54-
open var threadKey: pthread_t { return pthread_self() }
47+
static var envVarKey: pthread_key_t = {
48+
var envVarKey: pthread_key_t = 0
49+
if pthread_key_create( &envVarKey, { _ in
50+
_ = JNI.jvm?.pointee?.pointee.DetachCurrentThread( JNI.jvm )
51+
}) != 0 {
52+
JNI.report( "Could not create pthread envVarKey" )
53+
}
54+
return envVarKey
55+
}()
5556

5657
open var env: UnsafeMutablePointer<JNIEnv?>? {
57-
let currentThread = threadKey
58-
if let env = envCache[currentThread] {
59-
return env
58+
if let existing = pthread_getspecific( JNICore.envVarKey ) {
59+
return existing.assumingMemoryBound(to: JNIEnv?.self)
6060
}
6161

6262
let env = AttachCurrentThread()
63-
envLock.lock()
64-
envCache[currentThread] = env
65-
envLock.unlock()
63+
if pthread_setspecific( JNICore.envVarKey, env ) != 0 {
64+
JNI.report( "Could not set pthread specific env" )
65+
}
6666
return env
6767
}
6868

@@ -130,7 +130,9 @@ open class JNICore {
130130
return false
131131
}
132132

133-
self.envCache[threadKey] = tenv
133+
if pthread_setspecific( JNICore.envVarKey, tenv ) != 0 {
134+
JNI.report( "Could not set pthread specific tenv" )
135+
}
134136
self.api = self.env!.pointee!.pointee
135137
return true
136138
}
@@ -148,19 +150,21 @@ open class JNICore {
148150
open func GetEnv() -> UnsafeMutablePointer<JNIEnv?>? {
149151
var tenv: UnsafeMutablePointer<JNIEnv?>?
150152
if withPointerToRawPointer(to: &tenv, {
151-
JNI.jvm?.pointee?.pointee.GetEnv(JNI.jvm, $0, jint(JNI_VERSION_1_6) )
153+
JNI.jvm?.pointee?.pointee.GetEnv( JNI.jvm, $0, jint(JNI_VERSION_1_6 ) )
152154
} ) != jint(JNI_OK) {
153155
report( "Unable to get initial JNIEnv" )
154156
}
155157
return tenv
156158
}
157159

160+
fileprivate let initLock = NSLock()
161+
158162
private func autoInit() {
159-
envLock.lock()
160-
if envCache.isEmpty && !initJVM() {
163+
initLock.lock()
164+
if jvm == nil && !initJVM() {
161165
report( "Auto JVM init failed" )
162166
}
163-
envLock.unlock()
167+
initLock.unlock()
164168
}
165169

166170
open func background( closure: @escaping () -> () ) {
@@ -269,15 +273,15 @@ open class JNICore {
269273
if api.ExceptionCheck( env ) != 0, let throwable: jthrowable = api.ExceptionOccurred( env ) {
270274
report( "Exception occured", file, line )
271275
thrownLock.lock()
272-
thrownCache[threadKey] = throwable
276+
thrownCache[pthread_self()] = throwable
273277
thrownLock.unlock()
274278
api.ExceptionClear( env )
275279
}
276280
return result
277281
}
278282

279283
open func ExceptionCheck() -> jthrowable? {
280-
let currentThread: pthread_t = threadKey
284+
let currentThread: pthread_t = pthread_self()
281285
if let throwable: jthrowable = thrownCache[currentThread] {
282286
thrownLock.lock()
283287
thrownCache.removeValue(forKey: currentThread)

Sources/JNIObject.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ extension jobject {
156156
//
157157
//extension Array: JNIObjectProtocol where Element: JNIObjectProtocol {
158158
// public func localJavaObject( _ locals: UnsafeMutablePointer<[jobject]> ) -> jobject? {
159-
// return JNIType.toJava( value: map { JNIType.toJava( value: $0, locals: locals ).l }, locals: locals ).l
159+
// return JNIType.toJavaArray( value: self, locals: locals ) { JNIType.toJava( value: $0, locals: $1 ) }.l
160+
//// return JNIType.toJava( value: map { JNIType.toJava( value: $0, locals: locals ) }, locals: locals ).l
160161
// }
161162
//}
162163

Sources/JNIProxy.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ public class ClosureRunnable: Runnable {
134134

135135
public func run() {
136136
closure()
137-
JNI.envCache[JNI.threadKey] = nil
138137
}
139138

140139
}

0 commit comments

Comments
 (0)