Diggory
(Diggory)
1
Hello, this may be a code smell, but I have three different classes at the top of my code that are all singletons with references to each other.
e.g. here's a simple reducer:
import Foundation
@main
struct Alpha {
static func main() {
print(Date())
print("Alpha main()")
let bravo = Bravo.shared
bravo.doSomething()
RunLoop.main.run()
}
}
class Bravo {
// Singleton
public static let shared = Bravo()
private init() {
print("Bravo Singleton init()")
}
var charlie = Charlie.shared
var delta = Delta.shared
func doSomething() {
print("Bravo \(#function)")
}
}
class Charlie {
// Singleton
public static let shared = Charlie()
private init() {
print("Charlie Singleton init()")
}
var delta = Delta.shared
var bravo = Bravo.shared
func doSomething() {
print("Charlie \(#function)")
}
}
class Delta {
// Singleton
public static let shared = Delta()
private init() {
print("Delta Singleton init()")
}
var bravo = Bravo.shared
var charlie = Charlie.shared
func doSomething() {
print("Delta \(#function)")
}
}
If I try and set them all up then some kind of internal breakpoint is triggered and execution stops. (Thread 1: EXC_BREAKPOINT (code=1, subcode=0x100893adc))
I'm afraid that I'm not that familiar with multi-threading and tend to just avoid it if at all possible (as far as I can tell there's no multithreading in my code here.)
Xcode's Debug navigator appears to show that all my code is being run on one thread.
What's going on here? What have I got wrong? I assume that it's something to do with the circularity.
Thanks.
(I haven't marked any of the references to singletons as weak as they all last the lifetime of the executable. I know that this is wrong, but does it matter?)
1 Like
Diggory
(Diggory)
2
By clicking on the #0 _dispatch_once_wait.cold.1 () in the Debug Navigator I was shown some assembly which mentioned BUG IN CLIENT OF LIBDISPATCH: trying to lock recursively"
I think that having all the shared instances as properties of each other caused some unwanted recursion. I managed to fix it by making all the singleton properties lazy.
1 Like
Joe_Groff
(Joe Groff)
3
You are correct. Global variable initializers cannot be mutually dependent, so the circular dependency between global initializers causes the program to fail dynamically when the circularity is detected.
3 Likes