Can't use Siesta on an XPC service
I'm trying to use Siesta and all of my networking and storage code happens on an XPC service, but it always crashes because Siesta has a check for the main thread. The issue is that there's no main thread on an XPC service.
Good question. This had never even occurred to me! I'd always imagined Siesta operating within apps.
The real constraint is not that all operations happen on the main thread specifically, but rather that all operations for a given service and all of its resources happen on the same thread. I know very little about XPC. Can it guarantee that your code is consistently called on the same thread / GCD queue? (Or if not, can you use GCD to single-queue operations yourself?)
For the more common case of people writing apps, I don’t want to lose that main thread precondition.
One approach would be to give every Service instance an immutable “correct thread” property that records the thread the Service was created on, but (1) I'm not sure there’s a well-defined way of checking thread equality and (2) passing the preferred thread everywhere Siesta needs to check it could have nasty ripple effects.
Any thoughts?
Can it guarantee that your code is consistently called on the same thread / GCD queue? (Or if not, can you use GCD to single-queue operations yourself?)
I believe the answer is yes. GCD works on XPC services and I can configure a queue to run all of the networking operations.
One approach would be to give every Service instance an immutable “correct thread” property that records the thread the Service was created on, but (1) I'm not sure there’s a well-defined way of checking thread equality and (2) passing the preferred thread everywhere Siesta needs to check it could have nasty ripple effects.
Maybe there could be an option to disable the thread precondition? Since XPC is an advanced topic, you can assume the person using it would know the consequences.
This might be a bit of a hack but at least its surgical and it opens up a way to specify the "main thread" for the developer. She needs to set
DispatchQueue. siestaMainThread = myThread before making any calls to the Siesta API.
I've not tried nor tested this. Just sharing an idea. :-)
extension DispatchQueue
{
public static var siestaMainThread: Thread = Thread.main
internal static func mainThreadPrecondition(caller: String = #function)
{
precondition(
Thread.current.isEqual (DispatchQueue.siestaMainThread),
"Illegal attempt to use Siesta method \"\(caller)\" from a background thread. " +
"Except in specific situations, you must call Siesta APIs from its disignated main thread. " +
"See https://bustoutsolutions.github.io/siesta/guide/threading/")
}
}