Skip to content

Instantly share code, notes, and snippets.

@timboudreau
Created September 14, 2025 08:30
Show Gist options
  • Select an option

  • Save timboudreau/f5c56fb85639fab45db866aef6ddf92c to your computer and use it in GitHub Desktop.

Select an option

Save timboudreau/f5c56fb85639fab45db866aef6ddf92c to your computer and use it in GitHub Desktop.
A friendly wrapper around `setiopolicy_np` for iOS / Mac OS
/// A friendly wrapper around `setiopolicy_np`.
public enum IOPolicies {
case DontResolveSymlinks
case DiskIONormal
case DiskIOPassive
case DiskIOThrottled
case DiskIOImportant
case MaterializeVirtualFiles
case DontMaterializeVirtualFiles
case BackgroundIOImportant
private var scope : Int32 {
switch self {
case .BackgroundIOImportant: IOPOL_SCOPE_DARWIN_BG
default: IOPOL_SCOPE_THREAD
}
}
private var policyType : Int32 {
switch self {
case .DontResolveSymlinks: IOPOL_TYPE_VFS_TRIGGER_RESOLVE
case .DiskIONormal, .DiskIOPassive, .DiskIOThrottled, .DiskIOImportant, .BackgroundIOImportant: IOPOL_TYPE_DISK
case .MaterializeVirtualFiles, .DontMaterializeVirtualFiles: IOPOL_TYPE_VFS_MATERIALIZE_DATALESS_FILES
}
}
private var policyValue : Int32 {
switch self {
case .DontResolveSymlinks: IOPOL_VFS_TRIGGER_RESOLVE_OFF
case .DiskIONormal: IOPOL_NORMAL
case .DiskIOPassive: IOPOL_PASSIVE
case .DiskIOThrottled: IOPOL_THROTTLE
case .DiskIOImportant, .BackgroundIOImportant: IOPOL_IMPORTANT
case .MaterializeVirtualFiles: IOPOL_MATERIALIZE_DATALESS_FILES_ON
case .DontMaterializeVirtualFiles: IOPOL_MATERIALIZE_DATALESS_FILES_OFF
}
}
private func set() -> Bool {
setiopolicy_np(policyType, scope, policyValue) == 0
}
fileprivate func restore(_ oldValue : Int32) -> Bool {
setiopolicy_np(policyType, scope, oldValue) == 0
}
private var currentValue : Int32 {
getiopolicy_np(policyType, scope)
}
public var isInForce : Bool {
currentValue == policyValue
}
/// Apply this policy for the duration of the passed closure.
public func run<T>(_ f : () throws -> T) rethrows -> T {
let oldValue = currentValue
let changed = set()
defer {
if changed {
let _ = restore(oldValue)
}
}
return try f()
}
/// Apply this policy, returning an object which can restore the previous state
@discardableResult public func apply() -> Restorer? {
let oldValue = currentValue
if set() {
return Restorer(oldValue: oldValue, target: self)
}
return nil
}
public struct Restorer {
fileprivate let oldValue : Int32
fileprivate let target : IOPolicies
fileprivate let restored : AtomicBool = .init()
public func close() -> Bool {
if restored.exchange(true) {
return target.restore(oldValue)
}
return false
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment