Created
February 12, 2024 16:25
-
-
Save thomsmed/8a97e68aa6ed082300b692b9c17e8062 to your computer and use it in GitHub Desktop.
Snippet showing how to configure a CFRunLoopObserver.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// RunLoopObserving.swift | |
// | |
import Foundation | |
func name(for thread: Thread) -> String { | |
if let name = Thread.current.name, !name.isEmpty { | |
return name | |
} else { | |
return Thread.isMainThread ? "main" : "<unknown>" | |
} | |
} | |
func addTimer(to runLoop: RunLoop) { | |
let timer = Timer(timeInterval: 5, repeats: true) { _ in | |
print("[Thread: \(name(for: .current)), Timer] Timer fired") | |
} | |
runLoop.add(timer, forMode: .default) | |
} | |
func observe(_ runLoop: RunLoop) { | |
var runLoopContext = CFRunLoopObserverContext( | |
version: 0, | |
info: nil, | |
retain: nil, | |
release: nil, | |
copyDescription: nil | |
) | |
guard let runLoopObserver = CFRunLoopObserverCreate( | |
kCFAllocatorDefault, | |
CFRunLoopActivity.allActivities.rawValue, | |
true, | |
0, | |
{ runLoopObserver, runLoopActivity, info in | |
switch runLoopActivity { | |
case CFRunLoopActivity.entry: | |
print("[Thread: \(name(for: .current)), CFRunLoopObserver] Run Loop Event: entry") | |
case CFRunLoopActivity.beforeTimers: | |
print("[Thread: \(name(for: .current)), CFRunLoopObserver] Run Loop Event: beforeTimers") | |
case CFRunLoopActivity.beforeSources: | |
print("[Thread: \(name(for: .current)), CFRunLoopObserver] Run Loop Event: beforeSources") | |
case CFRunLoopActivity.beforeWaiting: | |
print("[Thread: \(name(for: .current)), CFRunLoopObserver] Run Loop Event: beforeWaiting") | |
case CFRunLoopActivity.afterWaiting: | |
print("[Thread: \(name(for: .current)), CFRunLoopObserver] Run Loop Event: afterWaiting") | |
case CFRunLoopActivity.exit: | |
print("[Thread: \(name(for: .current)), CFRunLoopObserver] Run Loop Event: exit") | |
default: | |
assertionFailure("Unknown Run Loop Event") | |
} | |
}, | |
&runLoopContext | |
) else { | |
return assertionFailure("Expected Observer creation to succeed") | |
} | |
CFRunLoopAddObserver( | |
runLoop.getCFRunLoop(), | |
runLoopObserver, | |
CFRunLoopMode.defaultMode | |
) | |
} | |
observe(.current) | |
addTimer(to: .current) | |
let thread = Thread { | |
Thread.current.name = "worker" | |
print("Started Thread: \(name(for: .current))") | |
observe(.current) | |
addTimer(to: .current) | |
RunLoop.current.run() | |
print("Exiting Thread: \(name(for: .current))") // Never called | |
} | |
thread.start() | |
RunLoop.current.run() | |
print("Exiting Thread: \(name(for: .current))") // Never called |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment