aboutsummaryrefslogtreecommitdiff
path: root/Sources/SleepInhibition.swift
diff options
context:
space:
mode:
Diffstat (limited to 'Sources/SleepInhibition.swift')
-rw-r--r--Sources/SleepInhibition.swift42
1 files changed, 42 insertions, 0 deletions
diff --git a/Sources/SleepInhibition.swift b/Sources/SleepInhibition.swift
new file mode 100644
index 0000000..0d9a05e
--- /dev/null
+++ b/Sources/SleepInhibition.swift
@@ -0,0 +1,42 @@
+#if canImport(IOKit.pwr_mgt)
+import IOKit.pwr_mgt
+
+func withSleepInhibited(operation: () async throws -> Void) async throws {
+ let assertionID = try {
+ var assertionID = IOPMAssertionID(0)
+ let ioReturn = IOPMAssertionCreateWithDescription(
+ kIOPMAssertionTypePreventUserIdleSystemSleep as CFString,
+ "caffeinate-downloads" as CFString,
+ "There are files being downloaded" as CFString,
+ nil, nil, 0, nil,
+ &assertionID
+ )
+ guard ioReturn == kIOReturnSuccess else {
+ throw SleepInhibitionError("failed to inhibit sleep", ioReturn)
+ }
+ return assertionID
+ }()
+
+ do {
+ try await operation()
+ } catch is CancellationError {
+ }
+
+ let ioReturn = IOPMAssertionRelease(assertionID)
+ guard ioReturn == kIOReturnSuccess else {
+ throw SleepInhibitionError("failed to allow sleep", ioReturn)
+ }
+}
+
+struct SleepInhibitionError: CustomStringConvertible, Error {
+ let description: String
+
+ init(_ description: String, _ code: IOReturn) {
+ if let code = mach_error_string(code) {
+ self.description = "\(description): \(String(cString: code))"
+ } else {
+ self.description = "\(description): \(code)"
+ }
+ }
+}
+#endif