import Foundation /// Sorgt dafür, dass immer nur eine Onyx-Instanz läuft. /// /// Zwei Instanzen sind kein Schönheitsfehler: jede bringt eine eigene /// Zustandsmaschine, eigene Timer und eine eigene Animation auf dieselbe Notch /// mit. Das Ergebnis sieht aus wie ein Ruckler und ist keiner — es sind zwei /// Panels, die gegeneinander arbeiten. /// /// **Die zuletzt gestartete Instanz gewinnt.** Beim Entwickeln ist das die /// frisch gebaute. Die andere Reihenfolge — erste gewinnt — würde bedeuten, /// dass man nach jedem Build weiter die alte Fassung testet, ohne es zu merken. /// Für den normalen Gebrauch ist der Unterschied unsichtbar: Onyx hat kein /// Fenster, das man in den Vordergrund holen könnte. public enum SingleInstanceGuard { public enum Decision: Equatable, Sendable { /// Kein Konkurrent — weiterlaufen. case proceed /// Diese Instanzen zum Beenden auffordern, danach erneut prüfen. case terminateOthers([pid_t]) /// Ließen sich nicht beenden — diese Instanz tritt zurück. case standDown([pid_t]) } /// Alle fremden Instanzen. Die eigene fällt zuverlässig heraus, auch wenn /// sie mehrfach in der Liste steht — sich selbst zu beenden wäre der /// denkbar schlechteste Ausgang. public static func others(from allPIDs: [pid_t], selfPID: pid_t) -> [pid_t] { allPIDs.filter { $0 != selfPID } } public static func decide(otherPIDs: [pid_t]) -> Decision { otherPIDs.isEmpty ? .proceed : .terminateOthers(otherPIDs) } public static func decideAfterTermination(remainingPIDs: [pid_t]) -> Decision { remainingPIDs.isEmpty ? .proceed : .standDown(remainingPIDs) } }