DispatchQueue and Threads

Hi,

We are having some issues with threading / dispatch queues this week. Basically I’m wondering why the following “async” code has the output it does:

print(Thread.isMainThread) // true
DispatchQueue.main.async {
     print(Thread.isMainThread) // false (???)
}

Whereas this same code but with “sync" prints “true” “true”:

print(Thread.isMainThread) // true
DispatchQueue.main.sync {
     print(Thread.isMainThread) // true
}

This goes against what I thought I understood about Dispatch. Are there any threading guarantees made by DispatchQueue at all? Especially on the main queue. And if not, is there another construct we can use?

The issue is that we’re on Android (where the threading situation is cloudy at best to begin with) and the JNI (Java-Native Interface) has specific requirements about which threads its methods are run on. Let alone our graphics rendering code.

Basically, initialising and using the JNI in separate DispatchQueue.main.async blocks apparently does not end up on the same thread (and apparently neither of them are the main thread). I’m quite confused by this.

Are there any resources or docs to get up to scratch with the internals of Dispatch a bit better?

Thanks for your ears and eyes :)
– Geordie

1 Like

Hi,

We are having some issues with threading / dispatch queues this week. Basically I’m wondering why the following “async” code has the output it does:

print(Thread.isMainThread) // true
DispatchQueue.main.async {
     print(Thread.isMainThread) // false (???)
}

This is wrong.

Whereas this same code but with “sync" prints “true” “true”:

print(Thread.isMainThread) // true
DispatchQueue.main.sync {
     print(Thread.isMainThread) // true
}

This is expected, because dispatch_sync() on the main thread is... difficult.

This goes against what I thought I understood about Dispatch. Are there any threading guarantees made by DispatchQueue at all? Especially on the main queue. And if not, is there another construct we can use?

The issue is that we’re on Android (where the threading situation is cloudy at best to begin with) and the JNI (Java-Native Interface) has specific requirements about which threads its methods are run on. Let alone our graphics rendering code.

Basically, initialising and using the JNI in separate DispatchQueue.main.async blocks apparently does not end up on the same thread (and apparently neither of them are the main thread). I’m quite confused by this.

Are there any resources or docs to get up to scratch with the internals of Dispatch a bit better?

THe problem here is not Dispatch, it's how it's (mis-)ported to Android for now.

On other platforms, either you call dispatch_main() and there's no main thread anymore, or from the main thread you are supposed to drain the Main CFRunloop which in turn is integrated with dispatch (or rather the other way around: dispatch is integrated with the main CFRunloop) and the main queue acts as a source on the main CFRunloop.

Last I heard, Android has not done that. I tried to explain this on Independent main queue for Android by johnno1962 · Pull Request #299 · apple/swift-corelibs-libdispatch · GitHub which atm is still not resolved.

-Pierre

···

On Dec 21, 2017, at 10:57 AM, Geordie J via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

Hi,

We are having some issues with threading / dispatch queues this week. Basically I’m wondering why the following “async” code has the output it does:

print(Thread.isMainThread) // true
DispatchQueue.main.async {
     print(Thread.isMainThread) // false (???)
}

This is wrong.

Whereas this same code but with “sync" prints “true” “true”:

print(Thread.isMainThread) // true
DispatchQueue.main.sync {
     print(Thread.isMainThread) // true
}

This is expected, because dispatch_sync() on the main thread is... difficult.

actually it should deadlock, this is wrong ;)
dispatch_sync() on the main queue like I said has weird semantics, and doing dispatch_sync() from the main thread onto the main queue is illegal.

···

On Dec 22, 2017, at 10:59 AM, Pierre Habouzit via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

On Dec 21, 2017, at 10:57 AM, Geordie J via swift-corelibs-dev <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>> wrote:

This goes against what I thought I understood about Dispatch. Are there any threading guarantees made by DispatchQueue at all? Especially on the main queue. And if not, is there another construct we can use?

The issue is that we’re on Android (where the threading situation is cloudy at best to begin with) and the JNI (Java-Native Interface) has specific requirements about which threads its methods are run on. Let alone our graphics rendering code.

Basically, initialising and using the JNI in separate DispatchQueue.main.async blocks apparently does not end up on the same thread (and apparently neither of them are the main thread). I’m quite confused by this.

Are there any resources or docs to get up to scratch with the internals of Dispatch a bit better?

THe problem here is not Dispatch, it's how it's (mis-)ported to Android for now.

On other platforms, either you call dispatch_main() and there's no main thread anymore, or from the main thread you are supposed to drain the Main CFRunloop which in turn is integrated with dispatch (or rather the other way around: dispatch is integrated with the main CFRunloop) and the main queue acts as a source on the main CFRunloop.

Last I heard, Android has not done that. I tried to explain this on Independent main queue for Android by johnno1962 · Pull Request #299 · apple/swift-corelibs-libdispatch · GitHub which atm is still not resolved.

-Pierre
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

Hi Pierre

Hi,

We are having some issues with threading / dispatch queues this week.
Basically I’m wondering why the following “async” code has the output it
does:

*print(Thread.isMainThread) // true*
*DispatchQueue.main.async {*
* print(Thread.isMainThread) // false (???)*
*}*

This is wrong.

This is wrong as in, it should be the main thread? That’s what I thought.

Whereas this same code but with “sync" prints “true” “true”:

*print(Thread.isMainThread) // true*
*DispatchQueue.main.sync {*
* print(Thread.isMainThread) // true*
*}*

This is expected, because dispatch_sync() on the main thread is...
difficult.

This goes against what I thought I understood about Dispatch. Are there
any threading guarantees made by DispatchQueue at all? Especially on the
main queue. And if not, is there another construct we can use?

The issue is that we’re on Android (where the threading situation is
cloudy at best to begin with) and the JNI (Java-Native Interface) has
specific requirements about which threads its methods are run on. Let alone
our graphics rendering code.

Basically, initialising and using the JNI in separate
DispatchQueue.main.async blocks apparently does not end up on the same
thread (and apparently neither of them are the main thread). I’m quite
confused by this.

Are there any resources or docs to get up to scratch with the internals of
Dispatch a bit better?

THe problem here is not Dispatch, it's how it's (mis-)ported to Android
for now.

On other platforms, either you call dispatch_main() and there's no main
thread anymore, or from the main thread you are supposed to drain the Main
CFRunloop which in turn is integrated with dispatch (or rather the other
way around: dispatch is integrated with the main CFRunloop) and the main
queue acts as a source on the main CFRunloop.

Last I heard, Android has not done that. I tried to explain this on
Independent main queue for Android by johnno1962 · Pull Request #299 · apple/swift-corelibs-libdispatch · GitHub which atm is
still not resolved.

Ok this is the info I needed, thanks! Apparently the toolchain I’m running
has had this patch applied to it. That would explain why .sync doesn’t
deadlock, why .async isn’t on the main thread, and why running .main.async
repeatedly ends up running the blocks on different threads.

I will rebuild dispatch and try again.

Thanks,
Geordie

···

Pierre Habouzit <pierre@habouzit.net> schrieb am Fr. 22. Dez. 2017 um 19:59: > On Dec 21, 2017, at 10:57 AM, Geordie J via swift-corelibs-dev < > swift-corelibs-dev@swift.org> wrote:

-Pierre